/* date = July 30th 2023 7:45 pm */ #ifndef VN_SCENE_H #define VN_SCENE_H // sixten(IMPORTANT): The arena that the scene is compiled on // is assumed to be the same it runs on, i.e. the interpreter relies // on the memory addresses being the same during compilation and // runtime. // We also assume that the original text and tokenization remains in // memory, for the duration of the scene. //////////////////////////////// //~ sixten: Scene Compilation Types typedef u64 scene_line_entry_flag; enum { S_LineEntryFlag_NoClear = (1<<0), }; enum scene_opcode { S_Op_Invalid = 0, S_Op_Constant, S_Op_Nil, S_Op_True, S_Op_False, S_Op_Add, S_Op_Subtract, S_Op_Multiply, S_Op_Divide, S_Op_Equal, S_Op_Greater, S_Op_Less, S_Op_Negate, S_Op_Not, S_Op_DefineGlobal, S_Op_GetGlobal, S_Op_SetGlobal, S_Op_AwaitInput, S_Op_LineEntry = 0x80, // sixten(NOTE): All opcoodes above are reserved. }; struct scene_bytecode_chunk { scene_bytecode_chunk *Next; s64 Count; u8 Data[4096]; }; struct scene_annotated_bytecode_chunk { scene_annotated_bytecode_chunk *Next; string Name; s64 Count; u8 Data[4096]; }; struct scene_annotated_bytecode_bucket { scene_annotated_bytecode_chunk *First; scene_annotated_bytecode_chunk *Last; s64 Count; }; enum scene_value_kind { S_ValueKind_Number, S_ValueKind_Boolean, S_ValueKind_Pointer, }; struct scene_value { scene_value_kind Kind; union { r64 Number; b32 Boolean; u64 Pointer; }; }; struct scene_value_chunk { scene_value_chunk *Next; s64 Count; scene_value Values[512]; }; enum scene_precedence { S_Precedence_None, S_Precedence_Assignment, S_Precedence_Or, S_Precedence_And, S_Precedence_Equality, S_Precedence_Comparison, S_Precedence_Term, S_Precedence_Factor, S_Precedence_Unary, S_Precedence_Call, S_Precedence_Primary, }; typedef void scene_parse_function(struct scene_compiler *Compiler, b32 CanAssign); struct scene_parse_rule { scene_parse_function *PrefixRule; scene_parse_function *InfixRule; scene_precedence Precedence; }; struct scene_compiler { memory_arena *Arena; string Text; token *TokensBegin; token *TokensEnd; token *At; scene_annotated_bytecode_bucket GlobalScope; scene_annotated_bytecode_bucket ProcBuckets[32]; scene_annotated_bytecode_bucket *CurrentBucket; string CurrentName; scene_value_chunk *FirstValueChunk; scene_value_chunk *LastValueChunk; s64 ValueCount; }; //////////////////////////////// //~ sixten: Compiled Scene Types struct scene_proc { // sixten: scene data string Name; u8 *Data; s64 Count; // sixten: hash link scene_proc *Next; }; struct scene_proc_bucket { scene_proc *First; scene_proc *Last; }; struct compiled_scene { scene_proc_bucket Buckets[16]; scene_value *Values; s64 ValueCount; string Source; }; //////////////////////////////// //~ sixten: Scene Compiler Functions //- sixten: value helpers inline scene_value S_MakeNumber(r64 Value) { scene_value Result; Result.Kind = S_ValueKind_Number; Result.Number = Value; return(Result); } inline scene_value S_MakeBoolean(b32 Value) { scene_value Result; Result.Kind = S_ValueKind_Boolean; Result.Boolean = Value; return(Result); } inline scene_value S_MakePointer(void *Value) { scene_value Result; Result.Kind = S_ValueKind_Pointer; Result.Pointer = PointerToU64(Value); return(Result); } //- sixten: error messaging static void S_ParseError(scene_compiler *Compiler, char *Message) { InvalidCodepath; } //- sixten: bytecode helpers static void S_EmitByte(scene_compiler *Compiler, u8 Byte); static u64 S_MakeConstant(scene_compiler *Compiler, scene_value Value); static void S_EmitVariableLength(scene_compiler *Compiler, u64 Value); static u64 S_ReadVariableLength(u8 **BytePtr); static void S_EmitConstant(scene_compiler *Compiler, scene_value Value); static void S_SetEmissionTarget(scene_compiler *Compiler, string Target); static scene_annotated_bytecode_chunk *S_FindBytecodeChunkByName(scene_compiler *Compiler, string Name); //- sixten: parsing helpers static void S_AdvanceCompiler(scene_compiler *Compiler); static scene_parse_rule S_ParseRuleFromToken(scene_compiler *Compiler, token Token); static b32 S_MatchToken(scene_compiler *Compiler, token Token, token_kind Kind); static token S_ConsumeToken(scene_compiler *Compiler, token_kind Kind, char *Message); //- sixten: parsing static void S_ParseTopLevelDeclaration(scene_compiler *Compiler); static void S_ParseProcedure(scene_compiler *Compiler); static void S_ParseDeclaration(scene_compiler *Compiler); static void S_ParseVariableDeclaration(scene_compiler *Compiler); static void S_ParseVariable(scene_compiler *Compiler, b32 CanAssign); static void S_ParseNamedVariable(scene_compiler *Compiler, token *Token, b32 CanAssign); static void S_ParseLineEntry(scene_compiler *Compiler); static void S_ParseStatement(scene_compiler *Compiler); static void S_ParseExpression(scene_compiler *Compiler); static void S_ParseLiteral(scene_compiler *Compiler, b32 CanAssign); static void S_ParseNumber(scene_compiler *Compiler, b32 CanAssign); static void S_ParseGrouping(scene_compiler *Compiler, b32 CanAssign); static void S_ParseUnary(scene_compiler *Compiler, b32 CanAssign); static void S_ParseBinary(scene_compiler *Compiler, b32 CanAssign); static void S_ParsePrecedence(scene_compiler *Compiler, scene_precedence Precedence); //- sixten: debugging static string S_DisassembleBytecode(scene_compiler *Compiler, scene_annotated_bytecode_chunk *Chunk, memory_arena *Arena); //- sixten: api static compiled_scene S_ScriptFromText(memory_arena *Arena, string Text); #endif //VN_SCENE_H