Merge pull request #203 from ThakeeNathees/syntax-change

function and else if keywords are changed.
This commit is contained in:
Thakee Nathees 2022-04-17 07:49:52 +05:30 committed by GitHub
commit 2262089948
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 122 additions and 96 deletions

View File

@ -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.");
}

View File

@ -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

View File

@ -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

32
tests/examples/matrix.pk Normal file
View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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')

View File

@ -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")

View File

@ -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

View File

@ -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]

View File

@ -37,6 +37,7 @@ TEST_SUITE = {
"examples/fib.pk",
"examples/fizzbuzz.pk",
"examples/helloworld.pk",
"examples/matrix.pk",
"examples/pi.pk",
"examples/prime.pk",
),