@Override public Token parse() { Token next = first.getNext(); if (!next.isOperator(Operator.BRACKET_LEFT)) throw new RuntimeException("Expected '(' after WHILE, found: " + next); next = next.getNext(); testExp = new BooleanExpression(next, scope); next = testExp.parse(); if (!next.isOperator(Operator.BRACKET_RIGHT)) throw new RuntimeException("Expected ')' after WHILE condition, found: " + next); next = next.getNext(); if (!next.isNewline()) throw new RuntimeException("Expected newline, found: " + next); next = next.getNext(); Keyword[] target = {Keyword.END}; statements = new StatementGroup(next, target, scope); next = statements.parse(); return next.getNext(); }
@Override public void emitCode(GluonOutput code) { code.comment("Function: " + funcName.getValue()); String funcLabel = GluonFunction.getLabel(funcName.getValue()); // Setup variables passed in on stack for use int offset = 4; // + 4 * parameters.size(); int used = 4; for (Variable parameter : parameters) { int stackOffset = offset + used; used += 4; code.code(parameter.getLabel() + " EQU EBP + " + stackOffset); } // Function code.label(funcLabel); // Push BP code.code("PUSH EBP"); // Mov BP, SP code.code("MOV EBP, ESP"); // Local variables scope.emitCreateScope(code); // Push all reg code.code("PUSH EAX"); code.code("PUSH EBX"); code.code("PUSH ECX"); code.code("PUSH EDX"); // Actual function logic code.comment("Function code start"); logic.emitCode(code); code.comment("Function code end"); // Pop all reg code.code("POP EDX"); code.code("POP ECX"); code.code("POP EBX"); code.code("POP EAX"); // Local variables scope.emitDistroyScope(code); // Pop BP code.code("POP EBP"); // Ret paramaters code.code("RET"); scope.buildRestore(code, parameters, true); code.comment("Function end: " + funcName.getValue()); }
@Override public Token parse() { funcName = first.getNext(); if (!funcName.isIdentifier()) throw new RuntimeException("Expected identifier for function name, found: " + funcName); GluonFunction.registerFunction(funcName.getValue()); Token test = funcName.getNext(); if (!test.isOperator(Operator.BRACKET_LEFT)) throw new RuntimeException("Expected '(' for function parmater list, found: " + test); test = test.getNext(); while (test.isIdentifier()) { Variable param = new Variable(test, scope, true); parameters.add(param); test = param.parse(true); if (test.isOperator(Operator.COMMA)) test = test.getNext(); } if (!test.isOperator(Operator.BRACKET_RIGHT)) throw new RuntimeException("Expected ')' for function parmater list, found: " + test); test = test.getNext(); if (!test.isOperator(Operator.COLON) && !test.isOperator(Operator.BRACE_LEFT)) throw new RuntimeException("Expected ':' or '{' in function def, found: " + test); if (test.isOperator(Operator.COLON)) { test = funcName.getNext(); if (!test.isOperator(Operator.BRACKET_LEFT)) throw new RuntimeException("Expected '(' for function return list, found: " + test); test = test.getNext(); while (test.isIdentifier()) { returns.add(test); test = test.getNext(); if (test.isOperator(Operator.COMMA)) test = test.getNext(); } if (!test.isOperator(Operator.BRACKET_RIGHT)) throw new RuntimeException("Expected ')' for function return list, found: " + test); } if (!test.isOperator(Operator.BRACE_LEFT)) throw new RuntimeException("Expected opening brace for function logic, found: " + test); test = test.getNext(); if (!test.isNewline()) throw new RuntimeException("Expected newline before function logic, found: " + test); test = test.getNext(); Operator[] targets = {Operator.BRACE_RIGHT}; logic = new StatementGroup(test, targets, scope); test = logic.parse(); if (!test.isOperator(Operator.BRACE_RIGHT)) throw new RuntimeException("Expected closing brace for function logic, found: " + test); return test.getNext(); }