Releases: ArkScript-lang/Ark
Releases · ArkScript-lang/Ark
ArkScript v4.0.0
Changes for you, as a user
- macros are defined using
(macro name value)and(macro name (foo bar ...args) body)instead of!{name value}and!{name (foo bar ...args) body} quotekeyword got removed. You can emulate it with a macro:(macro quote (value) (fun () value))(it wasn't really a Lispquotein the first place...)- while loops have their own scope
- imports changed a lot: from
(import "path/to/file.ark")to java like imports (the root is deduced from the main script emplacement):(import path.to.file :foo :bar)- for more details, see the documentation
- you can format your code using the cli:
arkscript -f myfile.ark - new
dictdatatype: https://arkscript-lang.dev/docs/std/dict/
For more information, check the language documentation!
Technical changelog
Added
- more tests for the io builtins
- added lines and code coloration in the error context
- new dependency:
fmtlib - added the padding/instruction/argumentation values when displaying instructions in the bytecode reader
$reprmacro to get a string representation of a given node- added boost-ext/ut to write unit tests in C++
- basic ArkScript code formatter, available through the CLI:
arkscript -f|--format - comments are now tracked in the AST and attached to the nearest node below them
VM::forceReloadPlugins, to be used by the REPL to force reload the plugins and be sure that their symbols are all defined- added
help,save(save history to disk),history(print history),reset(reset vm and code) commands to the REPL - REPL can now show when a code block isn't terminated (prompt changes from
>to:) - more controls available inside the REPL
- fuzzing step in the CI
- better error reporting on unknown import
- check on the number of arguments passed to
type - warning when the formatter deletes comment(s) by mistake
- check on arguments passed to
list,concat,appendand friends to only push valid nodes (that produce a value) - introduced
Ark::internal::Passto describe compiler passes: they all output an AST (parser, import solver, macro processor, and optimizer for now) - add
-f(no-)importsolver,-f(no-)macroprocessorand-f(no-)optimizerto toggle on and off those compiler passes - added resolving
empty?as a macro when possible - added short-circuiting to
andandorimplementation - added
--checkto the formatter as an option: returns 0 if the code is correctly formatted, 1 otherwise - the name & scope resolution pass now checks for mutability errors
- compile-time checks for mutability errors with
append!,concat!andpop! - new
MAKE_CLOSURE <page addr>instruction, generated in place of aLOAD_CONSTwhen a closure is made - added
-fdump-irto dump the IR entities to a file named{file}.ark.ir - added 11 super instructions and their implementation to the VM
- support for the glob import syntax and symbol import syntax
- modify list and return a copy
(string:setAt string index char)(bound checked) - added in place list mutation:
(@= list|string index new_value),(@@= list|list<string> index1 index2 new_value|char)(bound checked) - compile time argument count check for
andandor - basic dead code elimination in the AST optimizer
- new operator
@@to get elements in list of lists / list of strings - new builtin
random, returning a random number between INT_MIN and INT_MAX, or in a custom range $as-isto paste a node inside a maro without evaluating it further; useful to stop recursive evaluation of nodes inside function macrosLOAD_SYMBOL_BY_INDEXinstruction, loading a local from the current scope by an index (0 being the last element added to the scope)STORE_FROM_INDEXandSET_VAL_FROM_INDEXinstructions for parity with the super instructions not using load by indexINCREMENT_BY_INDEXandDECREMENT_BY_INDEXinstructions for parity with the super instructions not using load by indexSTORE_TAIL_BY_INDEX,STORE_HEAD_BY_INDEX,SET_VAL_TAIL_BY_INDEX,SET_VAL_HEAD_BY_INDEXsuper instructions added for parity with the super instructions not using load by indexRESET_SCOPE_JUMPinstruction emitted at the end of a while loop to reset a scope so that we can create multiple variables and useLOAD_SYMBOL_BY_INDEX- instruction source location; two new bytecode tables were added: one for filenames, another for (page pointer, instruction pointer, file id, line), allowing the VM to display better error messages when the source is available
- show source location when a runtime error is thrown in the VM
LT_CONST_JUMP_IF_FALSEandLT_SYM_JUMP_IF_FALSEto compare a symbol to a const and a symbol to a symbol (respectively), then jump to an address if false (useful for while loops that check a simple(< x n)condition)LT_CONST_JUMP_IF_TRUE, counterpart ofLT_CONST_JUMP_IF_FALSEGT_CONST_JUMP_IF_TRUE, counterpart ofLT_CONST_JUMP_IF_TRUEGT_CONST_JUMP_IF_FALSE, counterpart ofLT_CONST_JUMP_IF_FALSEGT_SYM_JUMP_IF_FALSE, counterpart ofLT_SYM_JUMP_IF_FALSECALL_SYMBOLsuper instruction to load and call a symbol in a single instructionGET_FIELD_FROM_SYMBOLandGET_FIELD_FROM_SYMBOL_INDEXsuper instructions to get a field from a closure and push it to the stackEQ_CONST_JUMP_IF_TRUEandEQ_SYM_INDEX_JUMP_IF_TRUEto compare a symbol to a const and a symbol to a symbol (respectively), then jump to an address if true (useful for conditions that check a simple(= x n)condition)NEQ_CONST_JUMP_IF_TRUEas a super instruction counterpart toEQ_CONST_JUMP_IF_TRUENEQ_SYM_JUMP_IF_FALSE, counterpart ofLT_SYM_JUMP_IF_FALSEfor inequalityAT_SYM_SYMandAT_SYM_INDEX_SYM_INDEXsuper instructions, to get an element from a list in a single instruction, avoiding 2 push and 2 popCHECK_TYPE_OFandCHECK_TYPE_OF_BY_INDEXsuper instructions, to check the type of variable against a constant in a single instructionINCREMENT_STOREandDECREMENT_STOREsuper instructions, to update a value in place when incrementing/decrementing it by a set amountAPPEND_IN_PLACE_SYMandAPPEND_IN_PLACE_SYM_INDEXsuper instructionsPUSH_RETURN_ADDRESSinstruction now replaces the VM auto push of IP/PP- remove the stack swapping by pushing arguments in the reverse order by which they are loaded
- wasm export: we can now run ArkScript code on the web!
GET_CURRENT_PAGE_ADDRESSinstruction to push the current page address to the stackCALL_CURRENT_PAGEsuper instruction, calling the current page with a given number of arguments (avoid loading a page address on the stack, then popping it to perform the call)- new data type
Dict, which can be created with(dict "key" "value" ...), and manipulated withdict:get,dict:add,dict:contains,dict:remove,dict:keysanddict:size - added program name under `builtin__sys:programName
STORE_LENsuper instruction, to load a symbol by index and store its length (if it's a string or list) in a new variableAT_SYM_INDEX_CONSTsuper instruction, to load a value from a container using a constant as the index
Changed
- instructions are on 4 bytes: 1 byte for the instruction, 1 byte of padding, 2 bytes for an immediate argument
- enhanced the bytecode reader and its command line interface
- added the padding/instruction/argumentation values when displaying instructions in the bytecode reader
- fixed underline bug in the error context
- the str:format functions now expect strings following this syntax: https://fmt.dev/latest/syntax.html
- more documentation about the compiler implementation
- more documentation about the virtual machine
- closures can be now be compared field per field:
(= closure1 closure2)will work only if they have the same fields (name) and if the values match - macros are now defined like
(macro name value)/(macro name (args args args) body)/($if cond then else) - upgraded from C++17 to C++20
- new parser, new syntax for imports:
(import package.sub.file) - allow nodes to be empty when dumping the AST to JSON
- Macros can be declared inside a
beginblock within a cond macro and used in the scope surrounding the cond macro arkscript --versionandarkscript --helpnow output ArkScript version with the commit hashvoid Value::toString(std::ostream&, VM&)now becomesstd::string Value::toString(VM&)- removed
Node::operator<<to replace it withNode::debugPrint - fixed a bug in the compiler where one could pass a non-symbol to
let,mutorset, resulting in a compiler crash - fixed a bug in the macro processor where one could pass an unknown symbol to
argcountand crash the processor - fixed a bug in the compiler where one could pass something other than a list to
(fun)as the argument block, resulting in a crash - fixed a bug in the compiler generating non-callable functions
- fixed a bug in the macro processor generating invalid
let/mut/setnodes - fixed a bug in the macro processor allowing out-of-bounds access with
(macro test (@ [1 2 3] -5)) - fixed a bug in the VM which wrongfully allowed self concat in place:
(concat! lst lst) - fixed a bug in the compiler where one could "use" operators without calling them:
(print nil?) - fixed a bug in the compiler allowing the use of operators without any argument:
(+) - fixed a bug in the VM during error reporting when a non-function was used as a function
- refactored code inside the bytecode reader to promote code reuse
- fixed a bug in the compiler generating invalid
whilenodes - fixed a bug when passing the wrong number of arguments to a function inside an async call was crashing the VM because the function couldn't be named
...
ArkScript v4.0.0-18
Added
- added program name under
builtin__sys:programName
Changed
- execution contexts can be reused for async calls if they are not active, to avoid constantly requesting memory and creating (heavy) contexts
- if there is more than 5 contexts, the 6th one will be destroyed once it completes
- execution contexts are now marked as free to be reused (or deleted) once a value has been computed, without waiting for a call to
await - captures are not renamed anymore by the NameResolutionPass (which used to fully qualify captured names when possible, which isn't desirable: when you capture
&foo, you expect to be able to use.foonot.module:foo) - when loading a module, its mappings are loaded in the current scope instead of the global scope
- argument order in the CLI changed: the file to run (and its optional script arguments) are now last, to be more consistent with all the other existing tooling (Python, Docker...)
ArkScript v4.0.0-17
Added
GET_CURRENT_PAGE_ADDRESSinstruction to push the current page address to the stackCALL_CURRENT_PAGEsuper instruction, calling the current page with a given number of arguments (avoid loading a page address on the stack, then popping it to perform the call)- new data type
Dict, which can be created with(dict "key" "value" ...), and manipulated withdict:get,dict:add,dict:contains,dict:remove,dict:keysanddict:size
Changed
- the VM no longer stores a reference to the current function being called in the newly created scope
ArkScript v4.0.0-16
Added
- wasm export: we can now run ArkScript code on the web!
Changed
- renamed
string:formattoformat io:removeFilesis nowio:removeFileand works on a single file/path- renamed almost all builtins to prefix them with
builtin__, to have them proxied in the standard library (to be able to import and scope them properly) - new super instruction
CALL_BUILTIN_WITHOUT_RETURN_ADDRESSto optimize the proxied builtins, skipping the return address deletion
ArkScript v4.0.0-15
Added
LT_CONST_JUMP_IF_FALSEandLT_SYM_JUMP_IF_FALSEto compare a symbol to a const and a symbol to a symbol (respectively), then jump to an address if false (useful for while loops that check a simple(< x n)condition)LT_CONST_JUMP_IF_TRUE, counterpart ofLT_CONST_JUMP_IF_FALSEGT_CONST_JUMP_IF_TRUE, counterpart ofLT_CONST_JUMP_IF_TRUEGT_CONST_JUMP_IF_FALSE, counterpart ofLT_CONST_JUMP_IF_FALSEGT_SYM_JUMP_IF_FALSE, counterpart ofLT_SYM_JUMP_IF_FALSECALL_SYMBOLsuper instruction to load and call a symbol in a single instructionGET_FIELD_FROM_SYMBOLandGET_FIELD_FROM_SYMBOL_INDEXsuper instructions to get a field from a closure and push it to the stackEQ_CONST_JUMP_IF_TRUEandEQ_SYM_INDEX_JUMP_IF_TRUEto compare a symbol to a const and a symbol to a symbol (respectively), then jump to an address if true (useful for conditions that check a simple(= x n)condition)NEQ_CONST_JUMP_IF_TRUEas a super instruction counterpart toEQ_CONST_JUMP_IF_TRUENEQ_SYM_JUMP_IF_FALSE, counterpart ofLT_SYM_JUMP_IF_FALSEfor inequalityAT_SYM_SYMandAT_SYM_INDEX_SYM_INDEXsuper instructions, to get an element from a list in a single instruction, avoiding 2 push and 2 popCHECK_TYPE_OFandCHECK_TYPE_OF_BY_INDEXsuper instructions, to check the type of variable against a constant in a single instructionINCREMENT_STOREandDECREMENT_STOREsuper instructions, to update a value in place when incrementing/decrementing it by a set amountAPPEND_IN_PLACE_SYMandAPPEND_IN_PLACE_SYM_INDEXsuper instructionsPUSH_RETURN_ADDRESSinstruction now replaces the VM auto push of IP/PP- remove the stack swapping by pushing arguments in the reverse order by which they are loaded
Changed
- macros are now defined like
(macro name value)/(macro name (args args args) body)/($if cond then else)
ArkScript v4.0.0-14
Added
- instruction source location ; two new bytecode tables were added: one for filenames, another for (page pointer, instruction pointer, file id, line), allowing the VM to display better error messages when the source is available
- show source location when a runtime error is thrown in the VM
Changed
- VM stack size is now 4096 instead of 8192
Ark::CodeErrornow takes aCodeErrorContextto store the source (filename, line, column, expression) of an error
Removed
- removed
Value VM::resolve(const Value* val, Args&&... args), which has been deprecated in ArkScript v3.4.0
ArkScript v4.0.0-13
Added
$as-isto paste a node inside a maro without evaluating it further ; useful to stop recursive evaluation of nodes inside function macrosLOAD_SYMBOL_BY_INDEXinstruction, loading a local from the current scope by an index (0 being the last element added to the scope)STORE_FROM_INDEXandSET_VAL_FROM_INDEXinstructions for parity with the super instructions not using load by indexINCREMENT_BY_INDEXandDECREMENT_BY_INDEXinstructions for parity with the super instructions not using load by indexSTORE_TAIL_BY_INDEX,STORE_HEAD_BY_INDEX,SET_VAL_TAIL_BY_INDEX,SET_VAL_HEAD_BY_INDEXsuper instructions added for parity with the super instructions not using load by indexRESET_SCOPEinstruction emitted at the end of a while loop to reset a scope so that we can create multiple variables and useLOAD_SYMBOL_BY_INDEX
Changed
-bcroption can be given a source file, it will then be compiled before its bytecode is shown- magic numbers for tables start in bytecode files have been changed from 0x01, 0x02, 0x03 to 0xA1, 0xA2, 0xA3 (symbols, values, code) to make them stand out in hex editors
- magic numbers for value types in bytecode files have been changed from 0x01, 0x02, 0x03 to 0xF1, 0xF2, 0xF3 (number, string, function)
- numbers in the values table in bytecode files are no longer stringified but their IEEE754 representation is now encoded on 12 bytes (4 for the exponent, 8 for the mantissa)
- changed how scopes are stored inside the VM to enhance performances. All scope data are now contiguous!
- when possible, accessing variables from the current scope is compiled to a new instruction
LOAD_SYMBOL_BY_INDEX, to avoid the sometimes expansive lookup by id- this works inside normal scopes (introduced by while loops) and functions scopes, but not for closures
ArkScript v4.0.0-12
Added
- new builtin
random, returning a random number between INT_MIN and INT_MAX, or in a custom range $as-isto paste a node inside a maro without evaluating it further ; useful to stop recursive evaluation of nodes inside function macros
Changed
- upgraded fmtlib to 11.1.3-13
- allow capture in nested scope (before it was targeting only the current scope)
ArkScript v4.0.0-11
Added
- new operator
@@to get elements in list of lists / list of strings
Changed
- loops have their own scope: variables created inside a loop won't leak outside it
ArkScript v4.0.0-10
Added
- the name & scope resolution pass now checks for mutability errors
- compile time checks for mutability errors with
append!,concat!andpop! - new
MAKE_CLOSURE <page addr>instruction, generated in place of aLOAD_CONSTwhen a closure is made - added
-fdump-irto dump the IR entities to a file named{file}.ark.ir - added 11 super instructions and their implementation to the VM
- support for the glob import syntax and symbol import syntax
- modify list and return a copy
(string:setAt string index char)(bound checked) - added in place list mutation:
(@= list|string index new_value),(@@= list|list<string> index1 index2 new_value|char)(bound checked) - compile time argument count check for
andandor - basic dead code elimination in the AST optimizer
Changed
- the
Ark::VMclass is nowfinal - the
STOREinstruction has been renamedSET_VAL - the
STOREinstruction is emitted in place of theLETandMUTinstructions, without any mutability checking now io:writeFileno longer takes a mode and has been split intoio:writeFileandio:appendToFile- instructions are now positioned like this:
inst byte1 byte2 byte3- byte1 is 0 if the instruction takes a single argument on 16 bits, split on byte2 and byte3
- if the instruction takes two arguments, they each have 12 bits ; the second one is on byte1 and upper half of byte2, the first on lower half of byte2 and then byte3
- ast-to-json dump now supports macros
- the parser can detect ill-formed macros (that are seen as function macros while being value macros)
- adding a
CALL_BUILTIN <builtin> <arg count>super instruction - fixed formatting of comments after the last symbol in an import node
- renamed
str:xyzbuiltins tostring:xyzfor uniformity with the standard library string:findtakes an optional third argument, startIndex (where to start the lookup from, default 0list:setAtcan work with negative indexes, and is now bound checked- re-enabled the AST optimizer, only used for the main
arkscriptexecutable (not enabled when embedding arkscript, so that one can grab variables from the VM)
Removed
- removed
LETandMUTinstructions in favor of a single newSTOREinstruction - removed
SAVE_ENVinstruction