private static void initCompiler(ref Compiler_t compiler, FunctionType type) { compiler.enclosing = current; compiler.function = null; compiler.type = type; compiler.localCount = 0; compiler.scopeDepth = 0; compiler.function = Object.newFunction(); current = compiler; if (type != FunctionType.TYPE_SCRIPT) { current.function.name = Object.copyString(parser.previous._char_ptr, parser.previous.start, parser.previous.length); } Local local = current.locals[current.localCount++]; local.depth = 0; local.isCaptured = false; if (type != FunctionType.TYPE_FUNCTION) { local.name._char_ptr = "this\0".ToCharArray(); local.name.start = 0; local.name.length = 4; } else { local.name._char_ptr = new char[] { '\0' }; local.name.start = 0; local.name.length = 0; } current.locals[current.localCount - 1] = local; // C sharp fix. }
public static void markCompilerRoots() { Compiler_t compiler = current; while (compiler != null) { Memory.markObject((Obj)compiler.function); compiler = compiler.enclosing; } }
private static int resolveLocal(ref Compiler_t compiler, ref Token name) { for (int i = compiler.localCount - 1; i >= 0; i--) { Local local = compiler.locals[i]; if (identifiersEqual(ref name, ref local.name)) { if (local.depth == -1) { error("Cannot read local variable in its own intializer."); } return(i); } } return(-1); }
private static ObjFunction endCompiler() { emitReturn(); ObjFunction function = current.function; #if DEBUG_PRINT_CODE if (!parser.hadError) { Chunk_t _chunk = currentChunk(); Debug.disassembleChunk(ref _chunk, function.name != null ? function.name.chars : "<script>".ToCharArray()); } #endif current = current.enclosing; return(function); }
private static void function(FunctionType type) { Compiler_t compiler = new Compiler_t(); initCompiler(ref compiler, type); beginScope(); // Compile parameter list. consume(TokenType.TOKEN_LEFT_PAREN, "Expect '(' after function name."); if (!check(TokenType.TOKEN_RIGHT_PAREN)) { do { current.function.arity++; if (current.function.arity > 255) { errorAtCurrent("Cannot have more than 255 parameters."); } byte paramConstant = parseVariable("Expect parameter name."); defineVariable(paramConstant); }while (match(TokenType.TOKEN_COMMA)); } consume(TokenType.TOKEN_RIGHT_PAREN, "Expect ')' after parameters."); // The body. consume(TokenType.TOKEN_LEFT_BRACE, "Expect '{' before funciton body."); block(); // Create the function object. ObjFunction function = endCompiler(); emitBytes((byte)OpCode.OP_CLOSURE, makeConstant(Value.OBJ_VAL(function))); for (int i = 0; i < function.upvalueCount; i++) { emitByte((byte)(compiler.upvalues[i].isLocal ? 1 : 0)); emitByte(compiler.upvalues[i].index); } }
public static ObjFunction compile(char[] source) { Scanner.initScanner(source); Compiler_t compiler = new Compiler_t(); initCompiler(ref compiler, FunctionType.TYPE_SCRIPT); parser.hadError = false; parser.panicMode = false; advance(); while (!match(TokenType.TOKEN_EOF)) { declaration(); } ObjFunction function = endCompiler(); return(parser.hadError ? null : function); }
private static int addUpvalue(ref Compiler_t compiler, byte index, bool isLocal) { int upvalueCount = compiler.function.upvalueCount; for (int i = 0; i < upvalueCount; i++) { Upvalue upvalue = compiler.upvalues[i]; if (upvalue.index == index && upvalue.isLocal == isLocal) { return(i); } } if (upvalueCount == UINT8_COUNT) { error("Too many closure variables in function."); return(0); } compiler.upvalues[upvalueCount].isLocal = isLocal; compiler.upvalues[upvalueCount].index = index; return(compiler.function.upvalueCount++); }
private static int resolveUpvalue(ref Compiler_t compiler, ref Token name) { if (compiler.enclosing == null) { return(-1); } int local = resolveLocal(ref compiler.enclosing, ref name); if (local != -1) { compiler.enclosing.locals[local].isCaptured = true; return(addUpvalue(ref compiler, (byte)local, true)); } int upvalue = resolveUpvalue(ref compiler.enclosing, ref name); if (upvalue != -1) { return(addUpvalue(ref compiler, (byte)upvalue, false)); } return(-1); }