public void Delete(ObjString key) { if (table.ContainsKey(key.Chars)) { table.Remove(key.Chars); } }
private void Function(FunctionType type) { current = new Instance { type = type, enclosing = current }; current.function.name = ObjString.CopyString(parser.previous.Lexeme); BeginScope(); Consume(TokenType.LeftParen, "Expect '(' after function name."); if (!Check(TokenType.RightParen)) { do { current.function.arity += 1; if (current.function.arity > 255) { ErrorAtCurrent("Can't have more than 255 parameters."); } byte paramConst = ParseVariable("Expect parameter name."); DefineVariable(paramConst); } while (Match(TokenType.Comma)); } Consume(TokenType.RightParen, "Expect ')' after parameters."); Consume(TokenType.LeftBrace, "Expect '{' before function body."); Block(); ObjFunction fun = EndCompiler(); EmitBytes(OpCode.Constant, MakeConstant(Value.Obj(fun))); }
public Value this[ObjString key] { get { return(table[key.Chars]); } set { Set(key.Chars, value); } }
private void DefineNative(string name, Func <int, Value[], Value> func) { Push(Value.Obj(ObjString.CopyString(name))); Push(Value.Obj(new ObjNative { Func = func })); globals[stack[0].AsString] = stack[1]; Pop(); Pop(); }
private InterpretResult Run() { frame = frames[frameCount - 1]; while (true) { #if DEBUG writer.WriteLine("->[{0}]", string.Join(", ", stack.Take(stackTop).Select(v => v.ToString()))); frame.function.chunk.DisassembleInstruction(writer, frame.ip); #endif byte instruction = ReadByte(); switch ((OpCode)instruction) { case OpCode.Constant: Value constant = ReadConstant(); Push(constant); break; case OpCode.Nil: Push(Value.Nil); break; case OpCode.True: Push(Value.Bool(true)); break; case OpCode.False: Push(Value.Bool(false)); break; case OpCode.Pop: Pop(); break; case OpCode.GetLocal: { byte slot = ReadByte(); Push(frame.slots[slot]); break; } case OpCode.SetLocal: { byte slot = ReadByte(); frame.slots[slot] = Peek(0); break; } case OpCode.GetGlobal: { ObjString name = ReadString(); if (!globals.ContainsKey(name)) { RuntimeError("Undefined variable '{0}'.", name.Chars); return(InterpretResult.RuntimeError); } Value value = globals[name]; Push(value); break; } case OpCode.DefineGlobal: { ObjString name = ReadString(); globals[name] = Peek(0); Pop(); break; } case OpCode.SetGlobal: { ObjString name = ReadString(); if (!globals.ContainsKey(name)) { RuntimeError("Undefined variable {0}.", name.Chars); return(InterpretResult.RuntimeError); } globals[name] = Peek(0); break; } case OpCode.Equal: { Value b = Pop(); Value a = Pop(); Push(Value.Bool(a.IsEqual(b))); break; } case OpCode.Greater: { if (!Peek(0).IsNumber || !Peek(1).IsNumber) { RuntimeError("Operands must be numbers"); return(InterpretResult.RuntimeError); } double r = Pop().AsNumber; double l = Pop().AsNumber; Push(Value.Bool(l > r)); break; } case OpCode.Less: { if (!Peek(0).IsNumber || !Peek(1).IsNumber) { RuntimeError("Operands must be numbers"); return(InterpretResult.RuntimeError); } double r = Pop().AsNumber; double l = Pop().AsNumber; Push(Value.Bool(l < r)); break; } case OpCode.Add: { if (Peek(0).IsString&& Peek(1).IsString) { ObjString b = Pop().AsString; ObjString a = Pop().AsString; Push(Value.Obj(ObjString.CopyString(a.Chars + b.Chars))); } else if (Peek(0).IsNumber&& Peek(1).IsNumber) { double r = Pop().AsNumber; double l = Pop().AsNumber; Push(Value.Number(l + r)); } else { RuntimeError("Operands must be two numbers or two strings"); return(InterpretResult.RuntimeError); } break; } case OpCode.Subtract: { if (!Peek(0).IsNumber || !Peek(1).IsNumber) { RuntimeError("Operands must be numbers"); return(InterpretResult.RuntimeError); } double r = Pop().AsNumber; double l = Pop().AsNumber; Push(Value.Number(l - r)); break; } case OpCode.Multiply: { if (!Peek(0).IsNumber || !Peek(1).IsNumber) { RuntimeError("Operands must be numbers"); return(InterpretResult.RuntimeError); } double r = Pop().AsNumber; double l = Pop().AsNumber; Push(Value.Number(l * r)); break; } case OpCode.Divide: { if (!Peek(0).IsNumber || !Peek(1).IsNumber) { RuntimeError("Operands must be numbers"); return(InterpretResult.RuntimeError); } double r = Pop().AsNumber; double l = Pop().AsNumber; Push(Value.Number(l / r)); break; } case OpCode.Not: Push(Value.Bool(IsFalsy(Pop()))); break; case OpCode.Negate: if (!Peek(0).IsNumber) { RuntimeError("Operand must be a number"); return(InterpretResult.RuntimeError); } Push(Value.Number(-Pop().AsNumber)); break; case OpCode.Print: { writer.WriteLine("{0}", Pop()); break; } case OpCode.Jump: { ushort offset = ReadShort(); frame.ip += offset; break; } case OpCode.JumpIfFalse: { ushort offset = ReadShort(); if (IsFalsy(Peek(0))) { frame.ip += offset; } break; } case OpCode.Loop: { ushort offset = ReadShort(); frame.ip -= offset; break; } case OpCode.Call: { int argCount = ReadByte(); if (!CallValue(Peek(argCount), argCount)) { return(InterpretResult.RuntimeError); } frame = frames[frameCount - 1]; break; } case OpCode.Return: { Value result = Pop(); frameCount -= 1; if (frameCount == 0) { Pop(); return(InterpretResult.OK); } stackTop = frame.slots.Offset; Push(result); frame = frames[frameCount - 1]; break; } } } }
public bool ContainsKey(ObjString key) => table.ContainsKey(key.Chars);
private byte IdentifierConstant(Token name) { return(MakeConstant(Value.Obj(ObjString.CopyString(name.Lexeme)))); }