Skip to content

Commit

Permalink
Add optional else to if
Browse files Browse the repository at this point in the history
  • Loading branch information
paked committed Mar 22, 2019
1 parent 28dc870 commit da8ec7f
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 12 deletions.
29 changes: 27 additions & 2 deletions example.ls
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/*
func fib(n number) number {
if (n == 0 || n == 1) {
return n
Expand All @@ -7,6 +8,30 @@ func fib(n number) number {
}
n := fib(8);
*/

n
log
n := 2

if n == 0 {
g := 2

g
log

f := 13

f
log
} else {
z := 100

z
log
}

if n == 2 {
t := 33

t
log
}
46 changes: 43 additions & 3 deletions src/ast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ struct ASTNode_If {
ASTNode* condition;

ASTNode* block;
ASTNode* elseBlock;
};

struct Parameter {
Expand Down Expand Up @@ -354,6 +355,26 @@ ASTNode ast_makeIf(ASTNode condition, ASTNode block) {
node.cIf.block = (ASTNode*) malloc(sizeof(block));
*node.cIf.block = block;

node.cIf.elseBlock = 0;

return node;
}

ASTNode ast_makeIf(ASTNode condition, ASTNode block, ASTNode elseBlock) {
assert(block.type == AST_NODE_ROOT && elseBlock.type == AST_NODE_ROOT);

ASTNode node = {};
node.type = AST_NODE_IF;

node.cIf.condition = (ASTNode*) malloc(sizeof(condition));
*node.cIf.condition = condition;

node.cIf.block = (ASTNode*) malloc(sizeof(block));
*node.cIf.block = block;

node.cIf.elseBlock = (ASTNode*) malloc(sizeof(elseBlock));
*node.cIf.elseBlock = elseBlock;

return node;
}

Expand Down Expand Up @@ -557,15 +578,34 @@ bool ast_writeBytecode(ASTNode* node, Hunk* hunk, Scope* scope) {
hunk_write(hunk, OP_JUMP_IF_FALSE, 0);
hunk_write(hunk, 0, 0);

Instruction offsetPos = hunk_getCount(hunk) - 1;
Instruction nextStatementPos = hunk_getCount(hunk) - 1;

if (!ast_writeBytecode(node->cIf.block, hunk, &inner)) {
return false;
}

Instruction ifEndPos = hunk_getCount(hunk) - 1;
if (node->cIf.elseBlock != 0) {
Scope elseInner = {};
scope_init(&elseInner, scope);

hunk_write(hunk, OP_JUMP, 0);
hunk_write(hunk, 0, 0);

Instruction exitBlockPos = hunk_getCount(hunk) - 1;

hunk->code[nextStatementPos] = hunk_getCount(hunk) - 1 - nextStatementPos;

hunk->code[offsetPos] = ifEndPos - offsetPos;
if (!ast_writeBytecode(node->cIf.elseBlock, hunk, &elseInner)) {
return false;
}

Instruction endOfElsePos = hunk_getCount(hunk) - 1;
hunk->code[exitBlockPos] = endOfElsePos - exitBlockPos;
} else {
Instruction ifEndPos = hunk_getCount(hunk) - 1;

hunk->code[nextStatementPos] = ifEndPos - nextStatementPos;
}
} break;
case AST_NODE_NUMBER:
{
Expand Down
19 changes: 19 additions & 0 deletions src/bytecode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ enum OPCode : Instruction {
OP_TEST_OR, // ||
OP_TEST_AND, // &&

OP_JUMP,
OP_JUMP_IF_FALSE,

OP_LOG,
Expand Down Expand Up @@ -125,6 +126,7 @@ int hunk_disassembleInstruction(Hunk* hunk, int offset) {
SIMPLE_INSTRUCTION(OP_TEST_OR);

SIMPLE_INSTRUCTION2(OP_SET_LOCAL);
SIMPLE_INSTRUCTION2(OP_JUMP);
SIMPLE_INSTRUCTION2(OP_JUMP_IF_FALSE);
SIMPLE_INSTRUCTION2(OP_CALL);
SIMPLE_INSTRUCTION2(OP_RETURN);
Expand Down Expand Up @@ -297,6 +299,8 @@ ProgramResult vm_run(VM* vm) {
Value name = vm_stack_pop(vm);

if (name.type != VALUE_STRING) {
logf("ERROR: Expecting name in string format\n");

return PROGRAM_RESULT_RUNTIME_ERROR;
}

Expand All @@ -307,6 +311,8 @@ ProgramResult vm_run(VM* vm) {
Value name = vm_stack_pop(vm);

if (name.type != VALUE_STRING) {
logf("ERROR: Expecting name in string format\n");

return PROGRAM_RESULT_RUNTIME_ERROR;
}

Expand All @@ -326,6 +332,8 @@ ProgramResult vm_run(VM* vm) {
int arity = (int) READ();

if (func.type != VALUE_FUNCTION) {
logf("ERROR Expecting func to be a function\n");

return PROGRAM_RESULT_RUNTIME_ERROR;
}

Expand Down Expand Up @@ -361,6 +369,12 @@ ProgramResult vm_run(VM* vm) {
frame->ip += jumpOffset;
}
} break;
case OP_JUMP:
{
Instruction jumpOffset = READ();

frame->ip += jumpOffset;
} break;
case OP_NEGATE:
{
Value v = vm_stack_pop(vm);
Expand Down Expand Up @@ -401,6 +415,7 @@ ProgramResult vm_run(VM* vm) {
Value b = vm_stack_pop(vm); \
Value a = vm_stack_pop(vm); \
if (!VALUE_IS_NUMBER(a) || !VALUE_IS_NUMBER(b)) { \
logf("ERROR: values should be numbers\n");\
return PROGRAM_RESULT_RUNTIME_ERROR; \
} \
Value c = {}; \
Expand All @@ -419,6 +434,8 @@ ProgramResult vm_run(VM* vm) {
Value a = vm_stack_pop(vm);

if (!VALUE_IS_BOOL(a) || !VALUE_IS_BOOL(b)) {
logf("ERROR: values should be bools\n");

return PROGRAM_RESULT_RUNTIME_ERROR;
}

Expand All @@ -435,6 +452,8 @@ ProgramResult vm_run(VM* vm) {
Value a = vm_stack_pop(vm);

if (!VALUE_IS_BOOL(a) || !VALUE_IS_BOOL(b)) {
logf("ERROR: values should be bools\n");

return PROGRAM_RESULT_RUNTIME_ERROR;
}

Expand Down
4 changes: 4 additions & 0 deletions src/lexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ enum TokenType : uint32 {
TOKEN_FALSE,

TOKEN_IF,
TOKEN_ELSE,
TOKEN_FUNC,
TOKEN_RETURN,
TOKEN_VAR,
Expand Down Expand Up @@ -140,6 +141,7 @@ Token scanner_readIdentifier(Scanner* scn) {
// true
// false
// if
// else
// func
// var
// return
Expand All @@ -148,6 +150,8 @@ Token scanner_readIdentifier(Scanner* scn) {
t.type = TOKEN_TRUE;
} else if (strncmp(t.start, "func", 4) == 0) {
t.type = TOKEN_FUNC;
} else if (strncmp(t.start, "else", 4) == 0) {
t.type = TOKEN_ELSE;
}
} else if (t.len == 5) {
if (strncmp(t.start, "false", 5) == 0) {
Expand Down
4 changes: 4 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ int main(int argc, char** argv) {
hunk_write(&hunk, OP_RETURN, 0);
hunk_write(&hunk, 0, 0);

#ifdef DEBUG
hunk_disassemble(&hunk, "main");
#endif

VM vm = {0};

vm_load(&vm, &hunk);
Expand Down
14 changes: 12 additions & 2 deletions src/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,9 +337,19 @@ bool parser_parseIf(Parser* p, ASTNode* node) {
ASTNode block = {};

if (parser_parseBlock(p, &block)) {
*node = ast_makeIf(condition, block);
if (parser_expect(p, TOKEN_ELSE)) {
ASTNode elseBlock = {};

return true;
if (parser_parseBlock(p, &elseBlock)) {
*node = ast_makeIf(condition, block, elseBlock);

return true;
}
} else {
*node = ast_makeIf(condition, block);

return true;
}
}
}
}
Expand Down
21 changes: 18 additions & 3 deletions src/typing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -561,10 +561,25 @@ bool typeCheck(ASTNode* node, SymbolTable* symbols) {
return false;
}

SymbolTable childSymbols = {};
symbolTable_init(&childSymbols, symbols);
{
SymbolTable childSymbols = {};
symbolTable_init(&childSymbols, symbols);

if (!typeCheck(node->cIf.block, &childSymbols)) {
return false;
}
}

return typeCheck(node->cIf.block, &childSymbols);
if (node->cIf.elseBlock != 0) {
SymbolTable childSymbols = {};
symbolTable_init(&childSymbols, symbols);

if (!typeCheck(node->cIf.elseBlock, &childSymbols)) {
return false;
}
}

return true;
} break;
case AST_NODE_RETURN:
{
Expand Down
2 changes: 0 additions & 2 deletions src/value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,5 +166,3 @@ bool value_equals(Value left, Value right) {

return false;
}


0 comments on commit da8ec7f

Please sign in to comment.