mirror of
https://github.com/zekexiao/pocketlang.git
synced 2025-02-10 22:50:58 +08:00
documentations updated
This commit is contained in:
parent
39c3bb41a0
commit
3b36e9002e
55
README.md
55
README.md
@ -3,9 +3,15 @@
|
|||||||
<img src="https://user-images.githubusercontent.com/41085900/117528974-88fa8d00-aff2-11eb-8001-183c14786362.png" width="500" >
|
<img src="https://user-images.githubusercontent.com/41085900/117528974-88fa8d00-aff2-11eb-8001-183c14786362.png" width="500" >
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
**Pocketlang** is a small (~3000 semicollons) and fast functional programming language written in C. It's syntactically similar to Ruby and it can be learned in less than an hour. Including the compiler, bytecode VM and runtime, it's a standalone executable with zero external dependecies just as it's self descriptive name. The pocketlang VM can be embedded in another hosting program very easily.
|
**Pocketlang** is a small (~3000 semicollons) and fast functional programming
|
||||||
|
language written in C. It's syntactically similar to Ruby and it can be learned
|
||||||
|
in less than an hour. Including the compiler, bytecode VM and runtime, it's a
|
||||||
|
standalone executable with zero external dependecies just as it's self descriptive
|
||||||
|
name. The pocketlang VM can be embedded in another hosting program very easily.
|
||||||
|
|
||||||
The language is written using [Wren Language](https://wren.io/) and their wonderful book [craftinginterpreters](http://www.craftinginterpreters.com/) as a reference.
|
The language is written using [Wren Language](https://wren.io/) and their
|
||||||
|
wonderful book [craftinginterpreters](http://www.craftinginterpreters.com/) as
|
||||||
|
a reference.
|
||||||
|
|
||||||
### What pocketlang looks like
|
### What pocketlang looks like
|
||||||
|
|
||||||
@ -25,31 +31,52 @@ for i in 0..10
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
## Performance!
|
## Performance
|
||||||
|
|
||||||
The source files used to run benchmarks could be found at `test/benchmarks/` directory. They were ran using a small python script in the test directory.
|
All the tests are ran on, Windows10 (64bit), ASUS N552VX, Intel Core i7-6700HQ 2.6GHz
|
||||||
- PC: ASUS N552VX, Intel Core i7-6700HQ 2.6GHz, 12GB SODIMM Ram
|
with 12GB SODIMM Ram. And the language versions are: pocketlang (pre-alpha), wren v0.3.0,
|
||||||
- Lnaguages: pocketlang (pre-alpha), wren v0.3.0, python v3.7.4, ruby v2.7.2,
|
python v3.7.4, ruby v2.7.2.
|
||||||
|
|
||||||
![preformance2](https://user-images.githubusercontent.com/41085900/120123257-6f043280-c1cb-11eb-8c20-a42153268a0f.png)
|
![preformance](https://user-images.githubusercontent.com/41085900/120123257-6f043280-c1cb-11eb-8c20-a42153268a0f.png)
|
||||||
|
|
||||||
|
|
||||||
When it comes to loops pocketlang much faster (even faster than [wren](https://wren.io/), the language I'm using as a reference) because we have dedicated opcode instructions for iterations and calling builtin functions. And it's is a functional language, which makes is possible to avoid object orianted/ class instance creation overhead.
|
|
||||||
|
|
||||||
|
The source files used to run benchmarks could be found at `test/benchmarks/`
|
||||||
|
directory. They were ran using a small python script in the test directory.
|
||||||
|
|
||||||
## Building From Source
|
## Building From Source
|
||||||
|
|
||||||
It can be build from source easily without any depencency, requirenments or even a build system, just a c99 compatible compiler is enough. It can be compiled with the following command.
|
It can be build from source easily without any depencency, or additional
|
||||||
|
requirenments except for a c99 compatible compiler. And build systems are
|
||||||
|
optional. It can be compiled with the following command.
|
||||||
|
|
||||||
#### gcc/mingw
|
#### GCC
|
||||||
```
|
```
|
||||||
gcc -o pocket cli/*.c src/*.c -Isrc/include -lm -Wno-int-to-pointer-cast
|
gcc -o pocket cli/*.c src/*.c -Isrc/include -lm -Wno-int-to-pointer-cast
|
||||||
```
|
```
|
||||||
|
|
||||||
#### msvc
|
#### MSVC
|
||||||
```
|
```
|
||||||
cl /Fepocket cli/*.c src/*.c /Isrc/include && rm *.obj
|
cl /Fepocket cli/*.c src/*.c /Isrc/include && rm *.obj
|
||||||
```
|
```
|
||||||
|
|
||||||
For other compilers it's the same (If you weren't able to compile it, please report by [opening an issue](https://github.com/ThakeeNathees/pocketlang/issues/new)). In addition you can use some of our build scripts (Makefile, batch script for MSVC, SCons) in the `build/` directory. For more see [build from source docs](https://thakeenathees.github.io/pocketlang/Getting%20Started/build%20from%20source.html).
|
### For other compiler/IDE
|
||||||
|
|
||||||
|
1. Create an empty project file / makefile.
|
||||||
|
2. Add all C files in the src directory.
|
||||||
|
3. Add all C files in the cli directory (**not** recursively).
|
||||||
|
4. Add src/include to include path.
|
||||||
|
5. Compile.
|
||||||
|
|
||||||
|
If you weren't able to compile it, please report by [opening an issue](https://github.com/ThakeeNathees/pocketlang/issues/new)).
|
||||||
|
In addition you can use some of our build scripts (Makefile, batch script for MSVC, SCons)
|
||||||
|
in the `build/` directory. For more see [build from source docs](https://thakeenathees.github.io/pocketlang/Getting%20Started/build%20from%20source.html).
|
||||||
|
|
||||||
|
|
||||||
|
## References
|
||||||
|
- Bob Nystrom.(2021) *craftinginterpreters* [online] Available at: www.craftinginterpreters.com/ (Accessed January 2021)
|
||||||
|
|
||||||
|
- leonard schütz. (2020) *Dynamic Typing and NaN Boxing* [online] Available at: https://leonardschuetz.ch/blog/nan-boxing/ (Accessed December 2020)
|
||||||
|
|
||||||
|
- Bob Nystrom.(2011) *Pratt Parsers: Expression Parsing Made Easy* [online] Avaliable at: http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/ (Accessed December 2020)
|
||||||
|
|
||||||
|
- Carol E. Wolf of Pace University, adapted by P. Oser. *The Shunting Yard Algorithm* [online] Available at: http://mathcenter.oxford.emory.edu/site/cs171/shuntingYardAlgorithm/ (Accessed September 2020)
|
||||||
|
|
||||||
|
@ -3,11 +3,13 @@
|
|||||||
|
|
||||||
## Without a build script
|
## Without a build script
|
||||||
|
|
||||||
Pocketlang has zero dependencies and you don't even require a build system, just a c99 compiler is enought, and it can be compiled with the following command.
|
It can be build from source easily without any depencency, or additional
|
||||||
|
requirenments except for a c99 compatible compiler. And build systems are
|
||||||
|
optional. It can be compiled with the following command.
|
||||||
|
|
||||||
Using gcc
|
Using gcc
|
||||||
```
|
```
|
||||||
gcc -o pocket cli/*.c src/*.c -Isrc/include -lm
|
gcc -o pocket cli/*.c src/*.c -Isrc/include -lm -Wno-int-to-pointer-cast
|
||||||
```
|
```
|
||||||
|
|
||||||
Using MSVC
|
Using MSVC
|
||||||
@ -15,11 +17,22 @@ Using MSVC
|
|||||||
cl /Fepocket cli/*.c src/*.c /Isrc/include && rm *.obj
|
cl /Fepocket cli/*.c src/*.c /Isrc/include && rm *.obj
|
||||||
```
|
```
|
||||||
|
|
||||||
For other compilers it's the same (If you weren't able to compile it with any c99 compatible compiler, please report by [opening an issue](https://github.com/ThakeeNathees/pocketlang/issues/new)). And add ` -Wno-int-to-pointer-cast` for gcc to suppress those warnings emitted when nan-tagging is enabled.
|
For other compiler/IDE
|
||||||
|
|
||||||
|
1. Create an empty project file / makefile.
|
||||||
|
2. Add all C files in the src directory.
|
||||||
|
3. Add all C files in the cli directory (**not** recursively).
|
||||||
|
4. Add src/include to include path.
|
||||||
|
5. Compile.
|
||||||
|
|
||||||
|
If you weren't able to compile it, please report by [opening an issue](https://github.com/ThakeeNathees/pocketlang/issues/new)).
|
||||||
|
|
||||||
## Using a build script
|
## Using a build script
|
||||||
|
|
||||||
You could find some of the build script for different build system in the `build/` direcroty. If you don't find a scirpt for your prifered system, request on github by [opening an issue](https://github.com/ThakeeNathees/pocketlang/issues/new) or feel free to contribute one.
|
You could find some of the build script for different build system in the `build/`
|
||||||
|
direcroty. If you don't find a scirpt for your prifered system, request on github
|
||||||
|
by [opening an issue](https://github.com/ThakeeNathees/pocketlang/issues/new) or
|
||||||
|
feel free to contribute one.
|
||||||
|
|
||||||
## Makefile
|
## Makefile
|
||||||
|
|
||||||
@ -27,19 +40,37 @@ You could find some of the build script for different build system in the `build
|
|||||||
cd build && make
|
cd build && make
|
||||||
```
|
```
|
||||||
|
|
||||||
|
I haven't tested the makefile on different platforms except for "windows subsystem for linux".
|
||||||
|
And the makefile is still need to be imporved. If you find any problems with the script or
|
||||||
|
have any improvements, let us know in [github](https://github.com/ThakeeNathees/pocketlang).
|
||||||
|
|
||||||
|
|
||||||
## Batch script with MSVC
|
## Batch script with MSVC
|
||||||
|
|
||||||
```
|
```
|
||||||
cd build && build
|
cd build && build
|
||||||
```
|
```
|
||||||
You don't require to run the script from a Visual Studio .NET Command Prompt, It'll search for the MSVS installation path and use it to compile. But if it can't, try running on VS command prompt.
|
|
||||||
|
You don't need to run the script from a Visual Studio .NET Command Prompt,
|
||||||
|
It'll search for the MSVS installation path and use it to compile. But if it
|
||||||
|
can't, try running on VS command prompt.
|
||||||
|
|
||||||
## SCons
|
## SCons
|
||||||
|
|
||||||
pocketlang mainly focused on [scons](https://www.scons.org/), and it's recommended to use it for contributions since it has various configurations and compiler support. It's a python based build system. You need to have python 3.6+ installed in your development environment. To install scons run `python3 -m pip install scons`. Make sure it's version is 3.0+ and for Visual Studio 2019 it require v3.1.1+. In Linux if scons using python2 instead of 3 you'll have to edit `/usr/local/bin/scons` or `~/.local/bin/scons` to ensure that it points to `/usr/bin/env python3` and not `python`
|
pocketlang mainly focused on [scons](https://www.scons.org/), and it's
|
||||||
|
recommended to use it for contributions since it has various configurations
|
||||||
|
and compiler support. It's a python based build system. You need to have
|
||||||
|
python 3.6+ installed in your development environment. To install scons run
|
||||||
|
`python3 -m pip install scons`. Make sure it's version is 3.0+ and for Visual
|
||||||
|
Studio 2019 it require v3.1.1+. In Linux if scons using python2 instead of 3
|
||||||
|
you'll have to edit `/usr/local/bin/scons` or `~/.local/bin/scons` to ensure
|
||||||
|
that it points to `/usr/bin/env python3` and not `python`
|
||||||
|
|
||||||
```
|
```
|
||||||
cd build && scons
|
cd build && scons
|
||||||
```
|
```
|
||||||
|
|
||||||
You can specify the number of jobs scons to use to speed up the building process using the -j flag (-j6, -j8). To generate Visual Studio project files add `vsproj=true` argument when building. To compile using mingw in windows use `use_mingw=true` argument. If your build failed feel free to [open an issue](https://github.com/ThakeeNathees/pocketlang/issues/new).
|
You can specify the number of jobs scons to use to speed up the building process
|
||||||
|
using the -j flag (-j6, -j8). To generate Visual Studio project files add `vsproj=true`
|
||||||
|
argument when building. To compile using mingw in windows use `use_mingw=true` argument.
|
||||||
|
If your build failed feel free to [open an issue](https://github.com/ThakeeNathees/pocketlang/issues/new).
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
|
TODO
|
||||||
Lorem **ipsum** dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
|
||||||
|
@ -1,22 +1,4 @@
|
|||||||
|
|
||||||
# Functions
|
# Functions
|
||||||
|
|
||||||
```ruby
|
TODO
|
||||||
def f()
|
|
||||||
print('test')
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
## Another title
|
|
||||||
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
fn = func print('test') end
|
|
||||||
|
|
||||||
f2 = func(arg) print('arg =', arg) end
|
|
||||||
```
|
|
||||||
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,17 +1,5 @@
|
|||||||
|
|
||||||
# Variables
|
# Variables
|
||||||
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
|
|
||||||
|
|
||||||
```ruby
|
TODO
|
||||||
from os import clock as c
|
|
||||||
|
|
||||||
some_variable = 12
|
|
||||||
print(some_variable) ## prints 12
|
|
||||||
some_variable = 'testing'
|
|
||||||
print(some_variable) ## prints 'testing'
|
|
||||||
```
|
|
||||||
|
|
||||||
## More lorem ipsum
|
|
||||||
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
|
|
||||||
|
@ -8,8 +8,8 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
|
|
||||||
// TODO: Replace bufferFill with bufferWrite, and (maybe) shrink the buffer if
|
// The buffer "template" implementation of diferent types, defined in the
|
||||||
// it's more than enough.
|
// buffers.h header.
|
||||||
|
|
||||||
#define DEFINE_BUFFER(M__NAME, M__NAME_L, M__TYPE) \
|
#define DEFINE_BUFFER(M__NAME, M__NAME_L, M__TYPE) \
|
||||||
void M__NAME_L##BufferInit(M__NAME##Buffer* self) { \
|
void M__NAME_L##BufferInit(M__NAME##Buffer* self) { \
|
||||||
|
@ -7,7 +7,16 @@
|
|||||||
#define BUFFERS_TEMPLATE_H
|
#define BUFFERS_TEMPLATE_H
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "include/pocketlang.h"
|
|
||||||
|
// The macro 'DECLARE_BUFFER()' emulate the C++ template to declare and define
|
||||||
|
// different types of buffer objects.
|
||||||
|
|
||||||
|
// A buffer of type 'T' will contain a heap allocated array of 'T' with the
|
||||||
|
// capacity of 'Tbuffer.capacity' as 'T* Tbuffer.data'. When the capacity is
|
||||||
|
// filled with 'T' values (ie. Tbuffer.count == Tbuffer.capacity) the buffer's
|
||||||
|
// internal data array will be reallocate to a capacity of 'GROW_FACTOR' times
|
||||||
|
// it's last capacity.
|
||||||
|
|
||||||
|
|
||||||
#define DECLARE_BUFFER(M__NAME, M__NAME_L, M__TYPE) \
|
#define DECLARE_BUFFER(M__NAME, M__NAME_L, M__TYPE) \
|
||||||
typedef struct { \
|
typedef struct { \
|
||||||
|
@ -39,6 +39,10 @@
|
|||||||
// available in C++98.
|
// available in C++98.
|
||||||
#define ERROR_MESSAGE_SIZE 256
|
#define ERROR_MESSAGE_SIZE 256
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* TOKENS *
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
||||||
TK_ERROR = 0,
|
TK_ERROR = 0,
|
||||||
@ -187,10 +191,14 @@ static _Keyword _keywords[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Compiler Types ////////////////////////////////////////////////////////////
|
/*****************************************************************************
|
||||||
|
* COMPILIER INTERNAL TYPES *
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
// Precedence parsing references:
|
// Precedence parsing references:
|
||||||
// https://en.wikipedia.org/wiki/Shunting-yard_algorithm
|
// https://en.wikipedia.org/wiki/Shunting-yard_algorithm
|
||||||
|
// http://mathcenter.oxford.emory.edu/site/cs171/shuntingYardAlgorithm/
|
||||||
|
// http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PREC_NONE,
|
PREC_NONE,
|
||||||
|
@ -9,10 +9,21 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "var.h"
|
#include "var.h"
|
||||||
|
|
||||||
|
// Pocketlang compiler is a single pass compiler, which means it doesn't go
|
||||||
|
// throught the basic compilation pipline such as lexing, parsing (AST),
|
||||||
|
// analyzing, intermediate codegeneration, and target codegeneration one by one
|
||||||
|
// instead it'll generate the target code as it reads the source (directly from
|
||||||
|
// lexing to codegen). Despite it's faster than multipass compilers, we're
|
||||||
|
// restricted syntax-wise and from compiletime optimizations, yet we support
|
||||||
|
// "forward names" to call functions before they defined (unlike C/Python).
|
||||||
typedef struct Compiler Compiler;
|
typedef struct Compiler Compiler;
|
||||||
|
|
||||||
|
// This will take source code as a cstring, compiles it to pocketlang bytecodes
|
||||||
|
// and append them to the script's implicit main (the $SourceBody function).
|
||||||
bool compile(PKVM* vm, Script* script, const char* source);
|
bool compile(PKVM* vm, Script* script, const char* source);
|
||||||
|
|
||||||
|
// Mark the heap allocated ojbects of the compiler at the garbage collection
|
||||||
|
// called at the marking phase of vmCollectGarbage().
|
||||||
void compilerMarkObjects(PKVM* vm, Compiler* compiler);
|
void compilerMarkObjects(PKVM* vm, Compiler* compiler);
|
||||||
|
|
||||||
#endif // COMPILER_H
|
#endif // COMPILER_H
|
||||||
|
11
src/utils.c
11
src/utils.c
@ -64,14 +64,21 @@ uint32_t utilHashNumber(double num) {
|
|||||||
|
|
||||||
uint32_t utilHashString(const char* string) {
|
uint32_t utilHashString(const char* string) {
|
||||||
// FNV-1a hash. See: http://www.isthe.com/chongo/tech/comp/fnv/
|
// FNV-1a hash. See: http://www.isthe.com/chongo/tech/comp/fnv/
|
||||||
uint32_t hash = 2166136261u;
|
|
||||||
|
#define FNV_prime_32_bit 16777619u
|
||||||
|
#define FNV_offset_basis_32_bit 2166136261u
|
||||||
|
|
||||||
|
uint32_t hash = FNV_offset_basis_32_bit;
|
||||||
|
|
||||||
for (const char* c = string; *c != '\0'; c++) {
|
for (const char* c = string; *c != '\0'; c++) {
|
||||||
hash ^= *c;
|
hash ^= *c;
|
||||||
hash *= 16777619;
|
hash *= FNV_prime_32_bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
|
#undef FNV_prime_32_bit
|
||||||
|
#undef FNV_offset_basis_32_bit
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -203,7 +203,7 @@ struct Object {
|
|||||||
struct String {
|
struct String {
|
||||||
Object _super;
|
Object _super;
|
||||||
|
|
||||||
uint32_t hash; //< Hash value of the string.
|
uint32_t hash; //< 32 bit hash value of the string.
|
||||||
uint32_t length; //< Length of the string in \ref data.
|
uint32_t length; //< Length of the string in \ref data.
|
||||||
uint32_t capacity; //< Size of allocated \ref data.
|
uint32_t capacity; //< Size of allocated \ref data.
|
||||||
char data[DYNAMIC_TAIL_ARRAY];
|
char data[DYNAMIC_TAIL_ARRAY];
|
||||||
|
12
src/vm.h
12
src/vm.h
@ -133,12 +133,12 @@ PkHandle* vmNewHandle(PKVM* self, Var value);
|
|||||||
// working set '------------------------'
|
// working set '------------------------'
|
||||||
//
|
//
|
||||||
// First we preform a tree traversel from all the vm's root objects. such as
|
// First we preform a tree traversel from all the vm's root objects. such as
|
||||||
// temp references, handles, vm's running fiber, current compiler (if it has
|
// stack values, temp references, handles, vm's running fiber, current
|
||||||
// any) etc. Mark them (ie. is_marked = true) and add them to the working set
|
// compiler (if it has any) etc. Mark them (ie. is_marked = true) and add
|
||||||
// (the gray_list). Pop the top object from the working set add all of it's
|
// them to the working set (the gray_list). Pop the top object from the
|
||||||
// referenced objects to the working set and mark it black (try-color marking)
|
// working set add all of it's referenced objects to the working set and mark
|
||||||
// We'll keep doing this till the working set become empty, and at this point
|
// it black (try-color marking) We'll keep doing this till the working set
|
||||||
// any object which isn't marked is a garbage.
|
// become empty, and at this point any object which isn't marked is a garbage.
|
||||||
//
|
//
|
||||||
// Every single heap allocated objects will be in the VM's link list. Those
|
// Every single heap allocated objects will be in the VM's link list. Those
|
||||||
// objects which are reachable have marked (ie. is_marked = true) once the
|
// objects which are reachable have marked (ie. is_marked = true) once the
|
||||||
|
Loading…
Reference in New Issue
Block a user