BACK HOME

parserlang

(dm me if you have a better name)

things you probably already know:

anyway, on to the things you may not know

things you may not know: pv

because i made it to write parsers, one of the features i have planned is simple backtracking

like when you're (i was) writing a recursive descent parser with parser combinators, the concat combinator is hard to write in a non recursive way (you have to write your own stack)

so that's one feature i planned

then to have backtracking in a "sane" way, the values have to be immutable

at some point i thought "oh jq does basically the same thing right?" and copied the entire jv (jq value) implementation and called it pv

(and quickly found out how much the different jv kinds (types) reference internal details)

so i just copied (most of) the header files and some of the implementation for the more complex kinds

but now i'm mostly done with rewriting jv in a way that i like

so it has immutable values like jv and 9 kinds: null, bool, int, double, string, array, object, iterator, function (i split number into int and double, and added iterator and function)

it also has some functions with single or double dispatch - equal, hash, to_string

pl

now on top of pv i made pl, which is a based stack vm (like lua)

it's not too unusual (i think) - there are a couple of opcode sections:

i currently have functional iteration and function calls - both as normal function and as generator

there's also an assembler, which takes code like this:

def n1 num 4 def n2 num 34 def a arr n1 n2 defglobals add a defmain main func add // takes 2 arguments add ret endfunc func main pushglobal 0 pushint 15 pushint 52 call 2 ret endfunc

and a debug code executor (which can execute that assembled code):

main bytecode: PUSHGLOBAL 0 PUSHINT 15 PUSHINT 52 CALL 2 RET return value: .: 67 global 0: .: idk it has kind 8 (pl_func) global 1: .: [] ./0: 4.000000 ./1: 34.000000

oOoOoOoOo the compiler

and finally, i have a compiler (Try It Online!)

it's a simple tree walking / recursive descent compiler with no optimization

some optimizations that i could implement are:

reference

this is a reference if you want to write stuff in parserlang

amount of whitespace (including newlines) is not significant, and there are no semicolons or other statement delimiters

there are only single line comments with #

string literals are double quoted

there are a few escape sequences: \\, \", \n, \x## (hex escape code)

functions / generators

all functions are like generators

there are two ways to call a function: direct (normal function call) and using the gcall() builtin

a direct call acts like a normal function call - it returns one value at a time - and it adds a backtracking marker so the rest of the code is run with each value yielded from the call

a gcall() call returns a generator / iterator instead

statements

variable definition and assignment

variables are declared and defined at the same time using the keyword def: def <variable> = <value>

variable assignment is (as usual) <variable> = <value>

yield and return

return may have a value or not

it yields a value if it has one and then ends the execution of the function

yield always has a value

it yields the value and does not end the function

control flow

block statement is just a list of statements enclosed by {}

if statement is if <condition> then <body (statement or block)>

the condition does not need parentheses

there is no else or else if statement... :/

for statement is for <variable> in <expression (iterable)> do <body (statement or block)>

while statement is while <condition> do <body (statement or block)>

function definition

a function definition is fn <name>(<argument names>) <body (always a block)>

fun fact: i may have decided on no parentheses in if and while and defining functions with fn before i got into rust

scopes

all variables are confined to their scope, which starts at the definition and ends at the surrounding brackets (except in cases like if condition then def var = 3, where var's scope ends after the if statement (this is useless (why would you do this))

function definitions are also scoped like variables, but they are hoisted to the top of their scope like in javascript

builtins

there are a few builtin functions right now