Merge pull request #11 from ThakeeNathees/rename-language

language name changed to pocketlang
This commit is contained in:
Thakee Nathees 2021-05-08 16:40:57 +05:30 committed by GitHub
commit f8573b8d63
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 270 additions and 150 deletions

17
.gitignore vendored
View File

@ -1,21 +1,20 @@
# MiniScript ignore list
# PocketLang ignore list
build/
MiniScript/test/
src/test/
MiniScript/.import/
release/
debug/
bin/
test/bin/
[Rr]elease/
[Dd]ebug/
*__pycache__/
.vs/
.vscode/
x64/
build.py
config.json
run.bat
*.dblite
*.idb
*.pdb
*.exp
*.sln
*.vcxproj
*.vcxproj.filters

View File

@ -1,8 +1,14 @@
## MiniScript Language
# PocketLang
MiniScript is a simple, fast, embeddable, functional, dynamic-typed, bytecode-interpreted, scripting language written in C. It uses the [mark-and-sweep](https://en.wikipedia.org/wiki/Tracing_garbage_collection) method for garbage collection. MiniScript is is syntactically similar to Ruby. The frontend and expression parsing techniques were written using [Wren Language](https://wren.io/) and their wonderful book [craftinginterpreters](http://www.craftinginterpreters.com/) as a reference.
<p align="center" >
<img src="https://user-images.githubusercontent.com/41085900/117528974-88fa8d00-aff2-11eb-8001-183c14786362.png" width="500" >
</p>
### What MiniScript looks like
**PocketLang** is a simple and fast programming language written in C. It's syntactically similar to Ruby, but compatibility isn't the goal 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, as static/shared library or a generated single header version of the source, which makes it even effortless.
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
```ruby

View File

@ -1,34 +1,44 @@
Import('env')
import os
env.PROJECT_NAME = "MiniScript"
env.RUN_TARGET = os.path.join(env['variant_dir'], 'bin/miniscript')
env.PROJECT_NAME = "pocketlang"
env.RUN_TARGET = os.path.join(env['variant_dir'], 'bin/pocket')
## MiniScript source files
## TODO: automate types file generation.
## PocketLang source files
SOURCES = [
Glob('src/*.c'),
Glob('src/types/*.c'),
Glob('src/types/gen/*.c'),
]
## Compile miniscript lib.
vm = env.Library(
target = 'bin/miniscript',
source = SOURCES,
CPPPATH = ['include/'],
)
if env['lib_shared']:
## Compile pocketlang dynamic lib.
dll = env.SharedLibrary(
target = 'bin/pocket' + env['bin_suffix'],
source = SOURCES,
CPPPATH = ['include/'],
CPPDEFINES = [env['CPPDEFINES'], 'MS_DLL', 'MS_COMPILE'],
)
else:
## Compile pocketlang static lib.
lib = env.Library(
target = 'bin/pocket' + env['bin_suffix'],
source = SOURCES,
CPPPATH = ['include/'],
)
## Test executable
test = env.Program(
target = 'bin/miniscript',
source = ['test/main.c'],
CPPPATH = ['include/'],
LIBPATH = 'bin',
LIBS = 'miniscript',
)
env.Append(CPPPATH=['include/'])
Requires(test, vm)
## Test executable
test = env.Program(
target = 'bin/pocket' + env['bin_suffix'],
source = ['src/main/main.c'],
CPPPATH = ['include/'],
LIBPATH = 'bin',
LIBS = 'pocket' + env['bin_suffix'],
)
env.Append(CPPPATH=['include/'])
Requires(test, lib)

View File

@ -1,12 +1,6 @@
#!python
import os, subprocess, sys
def get_variant_dir(env):
ret = 'build/' + env['platform'] + '/' + env['target'] + '/'
if env['platform'] == 'windows':
return ret + env['bits'] + '/'
return ret
opts = Variables([], ARGUMENTS)
## Define our options
opts.Add(EnumVariable('platform', "Compilation platform", '', ['', 'windows', 'x11', 'linux', 'osx']))
@ -16,9 +10,9 @@ opts.Add(BoolVariable('use_llvm', "Use the LLVM / Clang compiler", False))
opts.Add(BoolVariable('use_mingw', "Use Mingw compiler", False))
opts.Add(BoolVariable('vsproj', "make a visual studio project", False))
opts.Add(BoolVariable('verbose', "use verbose build command", False))
opts.Add(BoolVariable('verbose', "use verbose build command", True))
opts.Add(BoolVariable('libs', "include unit tests in main", False))
opts.Add(BoolVariable('lib_shared', "Compile as a shared library (only).", False))
## Setup the Environment
DefaultEnvironment(tools=[]) ## not using any tools
@ -145,7 +139,8 @@ if not env['verbose']:
no_verbose(sys, env)
Export('env')
env['variant_dir'] = get_variant_dir(env)
env['variant_dir'] = 'build/' + env['target'] + '/'
env['bin_suffix'] = '' ## TODO: Maybe '.%s.%s' % (env['platform'], env['bits'])
SConscript('SConscript', variant_dir=env['variant_dir'], duplicate=0)
## --------------------------------------------------------------------------------

View File

@ -21,6 +21,30 @@ extern "C" {
// String representation of the value.
#define MS_VERSION_STRING "0.1.0"
// miniscript visibility macros. define MS_DLL for using miniscript as a
// shared library and define MS_COMPILE to export symbols.
#ifdef _MSC_VER
#define _MS_EXPORT __declspec(dllexport)
#define _MS_IMPORT __declspec(dllimport)
#elif defined(__GNUC__)
#define _MS_EXPORT __attribute__((visibility ("default")))
#define _MS_IMPORT
#else
#define _MS_EXPORT
#define _MS_IMPORT
#endif
#ifdef MS_DLL
#ifdef MS_COMPILE
#define MS_PUBLIC _MS_EXPORT
#else
#define MS_PUBLIC _MS_IMPORT
#endif
#else
#define MS_PUBLIC
#endif
// MiniScript Virtual Machine.
// it'll contain the state of the execution, stack, heap, and manage memory
// allocations.
@ -123,7 +147,7 @@ typedef struct {
// Initialize the configuration and set ALL of it's values to the defaults.
// Call this before setting any particular field of it.
void msInitConfiguration(msConfiguration* config);
MS_PUBLIC void msInitConfiguration(msConfiguration* config);
typedef enum {
RESULT_SUCCESS = 0,
@ -132,34 +156,34 @@ typedef enum {
} MSInterpretResult;
// Allocate initialize and returns a new VM
MSVM* msNewVM(msConfiguration* config);
MS_PUBLIC MSVM* msNewVM(msConfiguration* config);
// Clean the VM and dispose all the resources allocated by the VM.
void msFreeVM(MSVM* vm);
MS_PUBLIC void msFreeVM(MSVM* vm);
// Compile and execut file at given path.
MSInterpretResult msInterpret(MSVM* vm, const char* file);
MS_PUBLIC MSInterpretResult msInterpret(MSVM* vm, const char* file);
// Set a runtime error to vm.
void msSetRuntimeError(MSVM* vm, const char* format, ...);
MS_PUBLIC void msSetRuntimeError(MSVM* vm, const char* format, ...);
// Returns the associated user data.
void* msGetUserData(MSVM* vm);
MS_PUBLIC void* msGetUserData(MSVM* vm);
// Update the user data of the vm.
void msSetUserData(MSVM* vm, void* user_data);
MS_PUBLIC void msSetUserData(MSVM* vm, void* user_data);
// Encode types to var.
// TODO: user need to use vmPushTempRoot() for strings.
Var msVarBool(MSVM* vm, bool value);
Var msVarNumber(MSVM* vm, double value);
Var msVarString(MSVM* vm, const char* value);
MS_PUBLIC Var msVarBool(MSVM* vm, bool value);
MS_PUBLIC Var msVarNumber(MSVM* vm, double value);
MS_PUBLIC Var msVarString(MSVM* vm, const char* value);
// Decode var types.
// TODO: const char* should be copied otherwise it'll become dangling pointer.
bool msAsBool(MSVM* vm, Var value);
double msAsNumber(MSVM* vm, Var value);
const char* msAsString(MSVM* vm, Var value);
MS_PUBLIC bool msAsBool(MSVM* vm, Var value);
MS_PUBLIC double msAsNumber(MSVM* vm, Var value);
MS_PUBLIC const char* msAsString(MSVM* vm, Var value);
#ifdef __cplusplus
} // extern "C"

View File

@ -1,59 +0,0 @@
import sys, os
## A simple version of the build script.
MINI_BUILD_SCRIPT = '''\
import os
cc = 'gcc' ## '"tcc\\tcc"'
sources = [
'src/types/name_table.c',
'test/main.c',
]
def add_sources(path):
for file in os.listdir(path):
if file.endswith('.c'):
sources.append(
path + '/' + file if path != '.' else file)
add_sources('src/')
add_sources('src/types/gen')
cmd = '%s -Wno-int-to-pointer-cast -o miniscript -Iinclude %s' % (cc, ' '.join(sources))
print(cmd)
os.system(cmd)
'''
def main():
generate_files()
def log(*msg):
print("[ms:configure.py]", end='')
for _msg in msg:
print(' ' + _msg, end='')
print()
def generate_files():
log("generating types/buffer source files")
sys.path.insert(1, 'src/types/')
import buffergen
ec = buffergen.gen()
## .bat files are just for quick rebuild of the buffer templates in windows.
if sys.platform == 'win32':
with open('src/types/gen.bat', 'w') as f:
f.write('python buffergen.py')
with open('src/types/clean.bat', 'w') as f:
f.write('python buffergen.py --clean')
with open('build.py', 'w') as f:
f.write(MINI_BUILD_SCRIPT)
log('build.py generated')
log("buffer source files generated")
return ec
if __name__ == '__main__':
main()

View File

@ -15,30 +15,6 @@
#include <stdint.h>
#include <stdlib.h>
// miniscript visibility macros. define MS_DLL for using miniscript as a
// shared library and define MS_COMPILE to export symbols.
#ifdef _MSC_VER
#define _MS_EXPORT __declspec(dllexport)
#define MS_IMPORT __declspec(dllimport)
#elif defined(__GNUC__)
#define _MS_EXPORT __attribute__((visibility ("default")))
#define _MS_IMPORT
#else
#define _MS_EXPORT
#define _MS_IMPORT
#endif
#ifdef MS_DLL
#ifdef MS_COMPILE
#define MS_PUBLIC _MS_EXPORT
#else
#define MS_PUBLIC _MS_IMPORT
#endif
#else
#define MS_PUBLIC
#endif
// Set this to dump compiled opcodes of each functions.
#define DEBUG_DUMP_COMPILED_CODE 0

View File

@ -322,18 +322,20 @@ Var varAdd(MSVM* vm, Var v1, Var v2) {
} break;
case OBJ_LIST:
TODO;
case OBJ_MAP:
case OBJ_RANGE:
case OBJ_SCRIPT:
case OBJ_FUNC:
case OBJ_FIBER:
case OBJ_USER:
TODO;
break;
}
}
vm->fiber->error = stringFormat(vm, "Unsupported operand types for operator '-' "
vm->fiber->error = stringFormat(vm, "Unsupported operand types for operator '+' "
"$ and $", varTypeName(v1), varTypeName(v2));
return VAR_NULL;

View File

@ -1,6 +1,4 @@
## Ignore all generated source files.
*.gen.h
*.gen.c
gen/
*.bat
## Ignore the generated sources.
## TODO: use template and macros instead of generating the source.
gen/

View File

@ -50,9 +50,9 @@ def _gen():
header = ''
source = ''
with open('buffer.template.h', 'r') as f:
with open('buffer.c.template', 'r') as f:
header = f.read()
with open('buffer.template.c', 'r') as f:
with open('buffer.h.template', 'r') as f:
source = f.read()
for _data in GEN_LIST:

View File

@ -60,6 +60,8 @@ void msInitConfiguration(msConfiguration* config) {
MSVM* msNewVM(msConfiguration* config) {
// TODO: If the [config] is NULL, initialize a default one.
msReallocFn realloc_fn = defaultRealloc;
void* user_data = NULL;
if (config != NULL) {

View File

@ -10,5 +10,5 @@ start = os.clock()
for i in 0..10
print(fib(28))
end
print('elapsed: ', os.clock() - start, 's')
print('elapsed:', os.clock() - start, 's')

View File

@ -7,4 +7,4 @@ def fib(n):
start = time.process_time()
for i in range(0, 10):
print(fib(28))
print("elapsed: " + str(time.process_time() - start), 's')
print("elapsed: " + str(time.process_time() - start), ' s')

167
test/msvcmake.bat Normal file
View File

@ -0,0 +1,167 @@
@rem ------------------------------------------------------------------------------
@rem MIT License
@rem ------------------------------------------------------------------------------
@rem
@rem Copyright (c) 2021 Thakee Nathees
@rem
@rem Permission is hereby granted, free of charge, to any person obtaining a copy
@rem of this software and associated documentation files (the "Software"), to deal
@rem in the Software without restriction, including without limitation the rights
@rem to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
@rem copies of the Software, and to permit persons to whom the Software is
@rem furnished to do so, subject to the following conditions:
@rem
@rem The above copyright notice and this permission notice shall be included in all
@rem copies or substantial portions of the Software.
@rem
@rem THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
@rem IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@rem FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@rem AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
@rem LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
@rem OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
@rem SOFTWARE.
@rem ------------------------------------------------------------------------------
@echo off
:: TODO: Usage.
setlocal
:: To set color. (Ref : https://stackoverflow.com/questions/2048509/how-to-echo-with-different-colors-in-the-windows-command-line)
SETLOCAL EnableDelayedExpansion
for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
set "DEL=%%a"
)
if "%~1"=="" goto :ARGS_DONE
if "%~1"=="-h" goto :DISPLAY_HELP
if "%~1"=="-d" goto :SET_DLL_BUILD
goto :ARGS_DONE
:DISPLAY_HELP
echo Usage: msvcbuild [opt]
echo -h Display the help message
echo -d Compile as a dynamic library
goto :END
:SET_DLL_BUILD
set BUILD_DLL=true
goto :ARGS_DONE
:ARGS_DONE
if not defined INCLUDE goto :MSVC_INIT
goto :START
:MSVC_INIT
call :ColorText 0f "Not running on MSVM prompt, searching for one..."
echo.
:: Find vswhere
if exist "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" (
set VSWHERE_PATH="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe"
) else ( if exist "%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe" (
set VSWHERE_PATH="%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe"
) else (
call :ColorText 0c "Can't find vswhere.exe"
echo.
goto :NO_VS_PROMPT
))
:: Get the VC installation path
%VSWHERE_PATH% -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -latest -property installationPath > _path_temp.txt
set /p VSWHERE_PATH= < _path_temp.txt
del _path_temp.txt
if not exist "%VSWHERE_PATH%" (
echo Error: can't find VisualStudio installation directory
goto :NO_VS_PROMPT
)
call :ColorText 0f "Found at - "
echo %VSWHERE_PATH%
:: Initialize VC for X86_64
call "%VSWHERE_PATH%\VC\Auxiliary\Build\vcvars64.bat"
if errorlevel 1 goto :NO_VS_PROMPT
call :ColorText 0f "Initialized MSVC x86_64"
echo.
goto :START
:NO_VS_PROMPT
echo You must open a "Visual Studio .NET Command Prompt" to run this script
goto :END
:START
if not exist "bin" md "./bin"
set ADDNL_INCLUDE=/I..\include
set ADDNL_CPPFLAGS=/EHsc /MDd
if "%BUILD_DLL%" neq "true" goto :COMPILE
set ADDNL_DEFINES=/DMS_DLL /DMS_COMPILE
:COMPILE
call :ColorText 0f "Building porcess started"
echo.
set object_files=
:: Recursively loop all files in '.' matching *.c and compile.
for /r "..\src" %%f in (*.c) do (
for %%i in ("%%f") do (
call set "object_files=%%object_files%% bin\%%~ni.obj"
cl /nologo /c %ADDNL_INCLUDE% %ADDNL_DEFINES% %ADDNL_CPPFLAGS% "%%f" /Fobin\%%~ni.obj
if errorlevel 1 goto :FAIL
)
)
if "%BUILD_DLL%"=="true" goto :LINK_DLL
call :ColorText 0a "pocket.lib"
echo.
lib /nologo /OUT:bin\pocket.lib %object_files%
if errorlevel 1 goto :FAIL
call :ColorText 0a "pocket.exe"
echo.
cl /nologo %ADDNL_CPPFLAGS% %ADDNL_INCLUDE% %object_files% /Febin\pocket.exe
if errorlevel 1 goto :FAIL
goto :CLEAN
:LINK_DLL
call :ColorText 0a "pocket.dll"
echo.
link /nologo /dll /out:bin\pocket.dll /implib:bin\pocket.lib %object_files%
:CLEAN
for %%o in (%object_files%) do (
del "%%o"
)
echo.
call :ColorText 0a "Compilation Success"
echo.
goto :END
:FAIL
call :ColorText 0c "Build failed. See the error messages."
echo.
:END
endlocal
goto :eof
:: To set color. (Ref : https://stackoverflow.com/questions/2048509/how-to-echo-with-different-colors-in-the-windows-command-line)
:ColorText
echo off
<nul set /p ".=%DEL%" > "%~2"
findstr /v /a:%1 /R "^$" "%~2" nul
del "%~2" > nul 2>&1
goto :eof