43 if (
parser.panicMode) Synchronize();
47 uint8_t global = ParseVariable(
"Expect variable name.");
58 DefineVariable(global);
63 const char *interned = DoIntern(str);
70 if (scopeDepth > 0)
return 0;
71 return IdentifierConstant(&
parser.previous);
80 for (
int i = locals.size() -1; i >= 0; i--) {
82 if (locals[i].depth == -1) {
83 ErrorAt(
parser.previous,
"Cannot read from local variable in its own initializer.");
92 if (scopeDepth == 0)
return;
96 for (
int i = locals.size()-1; i >= 0; i--) {
97 if (locals[i].depth != -1 && locals[i].depth < scopeDepth) {
101 ErrorAt(
parser.previous,
"Variable with this name already declared in this scope.");
109 if (locals.size() > UINT8_MAX) {
110 ErrorAt(
parser.previous,
"Too many local variables in one chunk.");
115 locals.push_back(local);
119 locals[locals.size() -1].depth = scopeDepth;
123 if (scopeDepth > 0) {
137 switch (
parser.current.type) {
179 ExpressionStatement();
184 int loopStart = CurrentChunk()->code.size();
212 ExpressionStatement();
215 int loopStart = CurrentChunk()->code.size();
227 int incrementStart = CurrentChunk()->code.size();
235 loopStart = incrementStart;
245 if (exitJump != -1) {
282 EmitByte(instruction);
285 return CurrentChunk()->code.size() - 2;
289 int jump = CurrentChunk()->code.size() - offset - 2;
291 if (jump > UINT16_MAX) {
292 ErrorAt(
parser.previous,
"Too much code to jump over.");
295 CurrentChunk()->code[
offset] = (jump >> 8) & 0xff;
296 CurrentChunk()->code[offset + 1] = jump & 0xff;
313 while (locals.size() > 0 && locals[locals.size()-1].depth > scopeDepth) {
339 if (!Check(type))
return false;
351 int offset = CurrentChunk()->code.size() - loopStart + 2;
353 if (offset > UINT16_MAX) ErrorAt(
parser.previous,
"Loop body too large.");
355 EmitByte((offset >> 8) & 0xff);
356 EmitByte(offset & 0xff);
360 CurrentChunk()->Write(byte);
364 CurrentChunk()->Write(bytea);
365 CurrentChunk()->Write(byteb);
381 std::cerr <<
": " << message << std::endl;
382 std::cerr <<
"In script: " << source << std::endl;
387 if (
parser.panicMode)
return;
402 parser.current = scanner.ScanToken();
410 if (
parser.current.type == type) {
415 ErrorAt(
parser.current, message);
419 if (CurrentChunk()->code.size() == 0 || CurrentChunk()->code[CurrentChunk()->code.size()-1] !=
uscript::OP_RETURN) {
423 #ifdef DEBUG_PRINT_CODE
425 CurrentChunk()->Disassemble(
"code");
439 int constant = CurrentChunk()->AddConstant(value);
440 if (constant > UINT8_MAX) {
441 ErrorAt(
parser.previous,
"Too many constants in one chunk.");
450 int v_int = strtol(
parser.previous.start, &end, 10 );
451 if (end ==
parser.previous.start +
parser.previous.length) {
455 double value = strtod(
parser.previous.start, NULL);
470 ParsePrecedence(PREC_AND);
476 uint8_t argCount = 0;
480 if (argCount == 255) {
481 ErrorAt(
parser.previous,
"Cannot have more than 255 arguments.");
493 uint8_t
name = IdentifierConstant(&
parser.previous);
505 uint8_t argCount = ArgumentList();
516 ParsePrecedence(PREC_OR);
526 switch (operatorType) {
535 switch (
parser.previous.type) {
545 std::string str(
parser.previous.start+1,
parser.previous.start +
parser.previous.length - 1);
550 NamedVariable(
parser.previous, canAssign);
554 uint8_t getOp, setOp;
555 int arg = ResolveLocal(&name);
561 arg = IdentifierConstant(&name);
568 EmitBytes(setOp, (uint8_t)arg);
571 EmitBytes(getOp, (uint8_t)arg);
582 switch (operatorType) {
602 if (prefixRule == NULL) {
603 ErrorAt(
parser.previous,
"Expect expression.");
608 (*this.*prefixRule)(canAssign);
610 while (precedence <= GetRule(
parser.current.type)->precedence) {
613 (*this.*infixRule)(canAssign);
617 ErrorAt(
parser.previous,
"Invalid assignmnet target.");
674 auto ret = strings.insert(str);
675 return ret.first->c_str();
681 std::cerr <<
"Missing class definition for cpp class: " << classname << std::endl;
bool Check(TokenType type)
const char * DoIntern(const std::string &str)
BEGIN_PROLOG TPC Trig offset(g4 rise time) ProjectToHeight
void AddLocal(Token name)
uint8_t IdentifierConstant(Token *token)
void EmitByte(uint8_t byte)
void EmitLoop(int loopStart)
void DefineVariable(uint8_t global)
BEGIN_PROLOG could also be cerr
void Call(bool canAssign)
void Index(bool canAssign)
bool DoCompile(const char *_source, Chunk *chunk)
static bool identifiersEqual(uscript::Token *a, uscript::Token *b)
void SetSource(const char *_start)
void Consume(TokenType type, const char *message)
void Literal(bool canAssign)
uint8_t ParseVariable(const char *errorMessage)
void Binary(bool canAssign)
int EmitJump(uint8_t instruction)
void PatchJump(int offset)
void EmitBytes(uint8_t bytea, uint8_t byteb)
void NamedVariable(Token token, bool canAssign)
int ResolveLocal(Token *name)
void EmitConstant(Value value)
void SetChunk(Chunk *chunk)
uint8_t MakeConstant(Value value)
auto end(FixedBins< T, C > const &) noexcept
bool Match(TokenType type)
#define STRING_VAL(value)
void ErrorAt(Token &token, const char *message)
void DoRegister(const char *classname)
void Grouping(bool canAssign)
#define NUMBER_VAL(value)
#define INTEGER_VAL(value)
void Number(bool canAssign)
byte_as<> byte
Type of data size stored in bytes, in long long precision.
void Variable(bool canAssign)
static void PrintErrorAt(uscript::Token &token, const char *message, const char *source)
void String(bool canAssign)
void Unary(bool canAssign)
void ParsePrecedence(Precedence precedence)
void ExpressionStatement()
ParseRule * GetRule(TokenType type) const
void(Compiler::*)(bool) ParseFn