From 88c45cccac8f4a2113ac60c36540521cbf1cf273 Mon Sep 17 00:00:00 2001 From: Thakee Nathees Date: Sun, 17 Apr 2022 06:59:18 +0530 Subject: [PATCH] function and else if keywords are changed. - `func` keyword has change to `function`. - `elsif` changed to `else if` --- src/pk_compiler.c | 69 ++++++++++++++++++------------------- tests/examples/brainfuck.pk | 18 +++++----- tests/examples/fizzbuzz.pk | 4 +-- tests/examples/matrix.pk | 32 +++++++++++++++++ tests/examples/palette.pk | 19 ---------- tests/lang/basics.pk | 4 +-- tests/lang/closure.pk | 26 +++++++------- tests/lang/controlflow.pk | 31 ++++++++++++----- tests/lang/core.pk | 2 +- tests/lang/functions.pk | 2 +- tests/random/lisp_eval.pk | 10 +++--- tests/tests.py | 1 + 12 files changed, 122 insertions(+), 96 deletions(-) create mode 100644 tests/examples/matrix.pk delete mode 100644 tests/examples/palette.pk diff --git a/src/pk_compiler.c b/src/pk_compiler.c index 633855c..19d1548 100644 --- a/src/pk_compiler.c +++ b/src/pk_compiler.c @@ -115,7 +115,7 @@ typedef enum { TK_AS, // as TK_DEF, // def TK_NATIVE, // native (C function declaration) - TK_FUNC, // func (literal function) + TK_FUNCTION, // function (literal function) TK_END, // end TK_NULL, // null @@ -131,7 +131,6 @@ typedef enum { TK_WHILE, // while TK_FOR, // for TK_IF, // if - TK_ELSIF, // elsif TK_ELSE, // else TK_BREAK, // break TK_CONTINUE, // continue @@ -178,7 +177,7 @@ static _Keyword _keywords[] = { { "as", 2, TK_AS }, { "def", 3, TK_DEF }, { "native", 6, TK_NATIVE }, - { "func", 4, TK_FUNC }, + { "function", 8, TK_FUNCTION }, { "end", 3, TK_END }, { "null", 4, TK_NULL }, { "in", 2, TK_IN }, @@ -192,7 +191,6 @@ static _Keyword _keywords[] = { { "while", 5, TK_WHILE }, { "for", 3, TK_FOR }, { "if", 2, TK_IF }, - { "elsif", 5, TK_ELSIF }, { "else", 4, TK_ELSE }, { "break", 5, TK_BREAK }, { "continue", 8, TK_CONTINUE }, @@ -1180,8 +1178,7 @@ static void skipNewLines(Compiler* compiler) { matchLine(compiler); } -// Match semi collon, multiple new lines or peek 'end', 'else', 'elsif' -// keywords. +// Match semi collon, multiple new lines or peek 'end', 'else' keywords. static bool matchEndStatement(Compiler* compiler) { if (match(compiler, TK_SEMICOLLON)) { skipNewLines(compiler); @@ -1191,9 +1188,8 @@ static bool matchEndStatement(Compiler* compiler) { return true; // In the below statement we don't require any new lines or semicolons. - // 'if cond then stmnt1 elsif cond2 then stmnt2 else stmnt3 end' - if (peek(compiler) == TK_END || peek(compiler) == TK_ELSE || - peek(compiler) == TK_ELSIF) + // 'if cond then stmnt1 else if cond2 then stmnt2 else stmnt3 end' + if (peek(compiler) == TK_END || peek(compiler) == TK_ELSE) return true; return false; @@ -1433,7 +1429,7 @@ static void compileExpression(Compiler* compiler); static void exprLiteral(Compiler* compiler); static void exprInterpolation(Compiler* compiler); -static void exprFunc(Compiler* compiler); +static void exprFunction(Compiler* compiler); static void exprName(Compiler* compiler); static void exprOr(Compiler* compiler); @@ -1509,7 +1505,7 @@ GrammarRule rules[] = { // Prefix Infix Infix Precedence /* TK_AS */ NO_RULE, /* TK_DEF */ NO_RULE, /* TK_EXTERN */ NO_RULE, - /* TK_FUNC */ { exprFunc, NULL, NO_INFIX }, + /* TK_FUNCTION */ { exprFunction, NULL, NO_INFIX }, /* TK_END */ NO_RULE, /* TK_NULL */ { exprValue, NULL, NO_INFIX }, /* TK_IN */ { NULL, exprBinaryOp, PREC_TEST }, @@ -1523,7 +1519,6 @@ GrammarRule rules[] = { // Prefix Infix Infix Precedence /* TK_WHILE */ NO_RULE, /* TK_FOR */ NO_RULE, /* TK_IF */ NO_RULE, - /* TK_ELSIF */ NO_RULE, /* TK_ELSE */ NO_RULE, /* TK_BREAK */ NO_RULE, /* TK_CONTINUE */ NO_RULE, @@ -1676,7 +1671,7 @@ static void exprInterpolation(Compiler* compiler) { } -static void exprFunc(Compiler* compiler) { +static void exprFunction(Compiler* compiler) { compileFunction(compiler, true); } @@ -2489,8 +2484,8 @@ static void compileBlockBody(Compiler* compiler, BlockType type) { } TokenType next = peek(compiler); - while (!(next == TK_END || next == TK_EOF || ( - (type == BLOCK_IF) && (next == TK_ELSE || next == TK_ELSIF)))) { + while (!(next == TK_END || next == TK_EOF || + ((type == BLOCK_IF) && (next == TK_ELSE)))) { compileStatement(compiler); skipNewLines(compiler); @@ -2849,7 +2844,7 @@ static void compileExpression(Compiler* compiler) { parsePrecedence(compiler, PREC_LOWEST); } -static void compileIfStatement(Compiler* compiler, bool elsif) { +static void compileIfStatement(Compiler* compiler, bool else_if) { skipNewLines(compiler); compileExpression(compiler); //< Condition. @@ -2858,38 +2853,40 @@ static void compileIfStatement(Compiler* compiler, bool elsif) { compileBlockBody(compiler, BLOCK_IF); - if (match(compiler, TK_ELSIF)) { + if (match(compiler, TK_ELSE)) { - // Jump pass else. - emitOpcode(compiler, OP_JUMP); - int exit_jump = emitShort(compiler, 0xffff); //< Will be patched. + if (match(compiler, TK_IF)) { //< Compile 'else if'. + // Jump pass else. + emitOpcode(compiler, OP_JUMP); + int exit_jump = emitShort(compiler, 0xffff); //< Will be patched. - // if (false) jump here. - patchJump(compiler, ifpatch); + // if (false) jump here. + patchJump(compiler, ifpatch); - compilerEnterBlock(compiler); - compileIfStatement(compiler, true); - compilerExitBlock(compiler); + compilerEnterBlock(compiler); + compileIfStatement(compiler, true); + compilerExitBlock(compiler); - patchJump(compiler, exit_jump); + patchJump(compiler, exit_jump); - } else if (match(compiler, TK_ELSE)) { + } else { //< Compile 'else'. - // Jump pass else. - emitOpcode(compiler, OP_JUMP); - int exit_jump = emitShort(compiler, 0xffff); //< Will be patched. + // Jump pass else. + emitOpcode(compiler, OP_JUMP); + int exit_jump = emitShort(compiler, 0xffff); //< Will be patched. - patchJump(compiler, ifpatch); - compileBlockBody(compiler, BLOCK_ELSE); - patchJump(compiler, exit_jump); + patchJump(compiler, ifpatch); + compileBlockBody(compiler, BLOCK_ELSE); + patchJump(compiler, exit_jump); + } } else { patchJump(compiler, ifpatch); } - // elsif will not consume the 'end' keyword as it'll be leaved to be consumed - // by it's 'if'. - if (!elsif) { + // 'else if' will not consume the 'end' keyword as it'll be leaved to be + // consumed by it's 'if'. + if (!else_if) { skipNewLines(compiler); consume(compiler, TK_END, "Expected 'end' after statement end."); } diff --git a/tests/examples/brainfuck.pk b/tests/examples/brainfuck.pk index 53ebfd5..dd63727 100644 --- a/tests/examples/brainfuck.pk +++ b/tests/examples/brainfuck.pk @@ -51,52 +51,52 @@ def execute(expr) if ptr >= mem.length then list_append(mem, 0) end ## Decrement the data pointer (to point to the next cell to the left). - elsif c == '<' + else if c == '<' ptr -= 1 if ptr < 0 then assert(false, "ip < 0") end ## Increment (increase by one) the byte at the data pointer. - elsif c == '+' + else if c == '+' if mem[ptr] == 255 then mem[ptr] = 0 else mem[ptr] += 1 end ## Decrement (decrease by one) the byte at the data pointer. - elsif c == '-' + else if c == '-' if mem[ptr] == 0 then mem[ptr] = 255 else mem[ptr] -= 1 end ## output the byte at the data pointer. - elsif c == '.' + else if c == '.' write(str_chr(mem[ptr])) - elsif c == ',' + else if c == ',' assert(false, "Currently input isn't supported in pocketlang.") ## if the byte at the data pointer is zero, then instead of moving the ## instruction pointer forward to the next command, jump it forward to ## the command after the matching ] command. - elsif c == '[' and mem[ptr] == 0 + else if c == '[' and mem[ptr] == 0 open = 0 while true i += 1 if expr[i] == ']' and open == 0 then break end if expr[i] == '[' then open += 1 - elsif expr[i] == ']' then open -= 1 + else if expr[i] == ']' then open -= 1 end assert(open >= 0) end ## if the byte at the data pointer is nonzero, then instead of moving the ## instruction pointer forward to the next command, jump it back to the ## command after the matching [ command - elsif c == ']' and mem[ptr] != 0 + else if c == ']' and mem[ptr] != 0 open = 0 while true i -= 1 if expr[i] == '[' and open == 0 then break end if expr[i] == ']' then open -= 1 - elsif expr[i] == '[' then open += 1 + else if expr[i] == '[' then open += 1 end assert(open <= 0) end diff --git a/tests/examples/fizzbuzz.pk b/tests/examples/fizzbuzz.pk index 846dfbc..1ea6471 100644 --- a/tests/examples/fizzbuzz.pk +++ b/tests/examples/fizzbuzz.pk @@ -2,8 +2,8 @@ for i in 1..100 if i%3 == 0 and i%5 == 0 then print('fizzbuzz') - elsif i%3 == 0 then print('fizz') - elsif i%5 == 0 then print('buzz') + else if i%3 == 0 then print('fizz') + else if i%5 == 0 then print('buzz') else print(i) end end diff --git a/tests/examples/matrix.pk b/tests/examples/matrix.pk new file mode 100644 index 0000000..da10f38 --- /dev/null +++ b/tests/examples/matrix.pk @@ -0,0 +1,32 @@ + +## Multiply two matrices. + +## A is 3x3 matrix +A = [[1, 2, 3], + [4, 5, 6], + [7, 8, 9]] + +## B is 3x4 matrix. +B = [[4, 6, 3, 2], + [8, 7, 0, 2], + [6, 0, 9, 4]] + +## Result is 3x4 matrix. +R = [[0,0,0,0], + [0,0,0,0], + [0,0,0,0]] + +## Iterate through rows of A. +for i in 0..(A.length) + ## Iterate through columns of B. + for j in 0..(B[0].length) + for k in 0..(B.length) + R[i][j] += A[i][k] * B[k][j] + end + end +end + +for row in R + print(row) +end + diff --git a/tests/examples/palette.pk b/tests/examples/palette.pk deleted file mode 100644 index 87be16b..0000000 --- a/tests/examples/palette.pk +++ /dev/null @@ -1,19 +0,0 @@ - -## Run pocket palette.pk > palette.ppm -## Open palatte.ppm with any image viwer which support ppm image -## (ex: photoshop, gimp, libre office draw, ...) - -blue = 200 - -print("P3") -print(255, 255) -print(255) - -from lang import write -for r in 0..255 - for g in 0..255 - write(r, ' ', g, ' ', blue, ' ') - end - write('\n') -end - diff --git a/tests/lang/basics.pk b/tests/lang/basics.pk index acd125f..89e43d1 100644 --- a/tests/lang/basics.pk +++ b/tests/lang/basics.pk @@ -18,7 +18,7 @@ assert(0xa1b2c3 == 10597059 and 0xff == 255) assert(0xffffffffffffffff == 18446744073709551615) ## Lists test. -l1 = [1, false, null, func print('hello') end, true] +l1 = [1, false, null, function print('hello') end, true] assert(l1[4]) l1[3] = null; assert(!l1[3]) l1 = [] + [] ; assert(l1.length == 0) @@ -45,7 +45,7 @@ assert(math.ceil(1.1) == math.floor(2.9)) ## Logical statement test val = 0; a = false; b = true -get_true = func return true end +get_true = function return true end if a and b then assert(false) end if a or b then val = 42 else assert(false) end assert(val == 42) if get_true() or false then val = 12 end assert(val == 12) diff --git a/tests/lang/closure.pk b/tests/lang/closure.pk index 40331e0..ea61270 100644 --- a/tests/lang/closure.pk +++ b/tests/lang/closure.pk @@ -2,15 +2,15 @@ ## Simple upvalue. def f1 local = "foo" - return func + return function return local end end assert(f1()() == "foo") def add3(x) - return func(y) - return func(z) + return function(y) + return function(z) return x + y + z end end @@ -21,8 +21,8 @@ assert(add3(7)(6)(4) == 17); ## Upvalue external to the inner function. def f2 local = "bar" - return func - fn = func + return function + fn = function return local end return fn @@ -33,10 +33,10 @@ assert(f2()()() == "bar") ## Check if upvalues are shared between closures. def f3 local = "baz" - _fn1 = func(x) + _fn1 = function(x) local = x end - _fn2 = func + _fn2 = function return local end return [_fn1, _fn2] @@ -52,7 +52,7 @@ def f4 j = i ## 'i' is shared, but 'j' doesn't list_append( a, - func + function return x + j end ) @@ -66,13 +66,13 @@ assert(a[1]() == 21) def f5 l1 = 12 - return func ## c1 + return function ## c1 l2 = 34 - return func ## c2 + return function ## c2 l3 = 56 - return func ## c3 - return func ## c4 - return func ## c5 + return function ## c3 + return function ## c4 + return function ## c5 return l1 + l2 + l3 end end diff --git a/tests/lang/controlflow.pk b/tests/lang/controlflow.pk index 90ddb2f..b8e5004 100644 --- a/tests/lang/controlflow.pk +++ b/tests/lang/controlflow.pk @@ -1,27 +1,27 @@ ## If statements. variable = null ## Will be changed by the control flow. -unreachable = func assert(false, 'Unreachable') end +unreachable = function assert(false, 'Unreachable') end if true then variable = 42 else unreachable() end assert(variable == 42, 'If statement failed.') if false then unreachable() -elsif true then variable = null +else if true then variable = null else unreachable() end assert(variable == null) if false then unreachable() -elsif false then unreachable() -elsif false then unreachable() +else if false then unreachable() +else if false then unreachable() else variable = "changed" end assert(variable == "changed") if false then unreachable() -elsif true +else if true if false unreachable() - elsif true + else if true variable = 123 else unreachable() @@ -39,9 +39,9 @@ assert(variable == 1212) while true variable = 22 - if true then elsif false then end + if true then else if false then end if false - elsif true + else if true variable += 2300 end variable += 1 @@ -55,6 +55,21 @@ for k in map end assert(sum == 54) +val = 2 +if val == 1 then val = null +else if val == 2 then val = 'foo' +else val = null +end +assert(val == 'foo') + +val = 2 +if val == 1 then val = null +else + if val == 2 then val = 'bar' + end ##< Need an extra end since 'else if' != 'else \n if'. +end +assert(val == 'bar') + # If we got here, that means all test were passed. print('All TESTS PASSED') diff --git a/tests/lang/core.pk b/tests/lang/core.pk index 9509ef6..f2aae8c 100644 --- a/tests/lang/core.pk +++ b/tests/lang/core.pk @@ -26,7 +26,7 @@ assert([1, 2, 3].length == 3) ## Function assert(print.arity == -1) assert(hex.arity == 1) -assert(func(a, b)end .arity == 2) +assert(function(a, b)end .arity == 2) assert(print.name == "print") def fn(p1, p2, p3) end assert(fn.name == "fn") diff --git a/tests/lang/functions.pk b/tests/lang/functions.pk index a830f2a..4794864 100644 --- a/tests/lang/functions.pk +++ b/tests/lang/functions.pk @@ -9,7 +9,7 @@ assert(f3('a', 'b', 'c', 'd') == 'c') ## Local variables of inner funcions. def f4 l1 = 3.14 - f5 = func + f5 = function l2 = 42 return l2 end diff --git a/tests/random/lisp_eval.pk b/tests/random/lisp_eval.pk index df8a0b0..fc3b403 100644 --- a/tests/random/lisp_eval.pk +++ b/tests/random/lisp_eval.pk @@ -44,27 +44,27 @@ def eval(expr, ind) end return [val, ind] - elsif c == '+' + else if c == '+' r = binary_op(expr, ind) if not r[0] then return [null, -1] end return [r[1] + r[2], r[3]] - elsif c == '-' + else if c == '-' r = binary_op(expr, ind) if not r[0] then return [null, -1] end return [r[1] - r[2], r[3]] - elsif c == '*' + else if c == '*' r = binary_op(expr, ind) if not r[0] then return [null, -1] end return [r[1] * r[2], r[3]] - elsif c == '/' + else if c == '/' r = binary_op(expr, ind) if not r[0] then return [null, -1] end return [r[1] / r[2], r[3]] - elsif isnum(c) + else if isnum(c) val = str_ord(c) - str_ord('0') assert(0 <= val and val < 10) return [val, ind] diff --git a/tests/tests.py b/tests/tests.py index bfdabf1..ffeded7 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -37,6 +37,7 @@ TEST_SUITE = { "examples/fib.pk", "examples/fizzbuzz.pk", "examples/helloworld.pk", + "examples/matrix.pk", "examples/pi.pk", "examples/prime.pk", ),