/* 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 struct scene_compile_error { scene_compile_error *Next; string Message; token Token; }; struct scene_compile_error_list { scene_compile_error *First; scene_compile_error *Last; s64 Count; }; enum scene_opcode { S_Op_Invalid = 0, S_Op_Constant, S_Op_Pop, 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_Jump, S_Op_JumpClose, S_Op_AddBranch, S_Op_Halt, S_Op_AwaitInput, S_Op_ClearDialog, S_Op_LineEntry, S_Op_ShowCharacter, }; 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_Nil = 0, S_ValueKind_Number, S_ValueKind_Boolean, S_ValueKind_Pointer, S_ValueKind_SourceRef, S_ValueKind_String, S_ValueKind_Offset, }; struct scene_value { scene_value_kind Kind; union { r64 Number; b32 Boolean; u64 Pointer; range1_s64 SourceRef; string String; s64 Offset; }; }; 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; }; enum scene_emission_target_type { S_EmissionTarget_Raw, S_EmissionTarget_Named, }; struct scene_emission_target { memory_arena *Arena; scene_annotated_bytecode_bucket *Bucket; scene_emission_target_type Type; string Name; }; struct scene_branch_case { scene_branch_case *Next; token Name; scene_annotated_bytecode_bucket Bucket; scene_value *OffsetValue; scene_value *EndOffsetValue; }; struct scene_character_action { scene_character_action *Next; scene_character_action *Prev; string Target; character_state State; }; struct scene_compiler { memory_arena *Arena; b32 InPanicMode; b32 EncounteredError; scene_compile_error_list Errors; string Text; token *TokensBegin; token *TokensEnd; token *At; scene_annotated_bytecode_bucket GlobalScope; scene_annotated_bytecode_bucket ProcBuckets[32]; scene_emission_target TargetStack[16]; s32 TargetStackIndex; 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; scene_compile_error_list Errors; b32 IsValid; }; //////////////////////////////// //~ sixten: Scene Runtime Types struct scene_runtime_error { scene_runtime_error *Next; scene_runtime_error *Prev; string Message; }; struct scene_runtime_result { b32 HadError; b32 ReachedAwait; }; enum textbox_action_kind { TextboxActionKind_Set, TextboxActionKind_Append, }; struct textbox_action { textbox_action *Next; textbox_action_kind Kind; string String; }; struct branch_case { string Name; s64 Offset; }; struct scene_runtime_stack { scene_value Stack[128]; s32 Count; }; struct scene_runtime { compiled_scene Compiled; // sixten: runtime state memory_arena *RuntimeArena; scene_proc *CurrentProc; s64 IP; scene_runtime_stack Stack; // sixten: errors memory_arena *ErrorArena; scene_runtime_error *FirstError; scene_runtime_error *LastError; // sixten: branches branch_case Branches[16]; s64 BranchCount; // sixten: result textbox_action *FirstTextboxAction; textbox_action *LastTextboxAction; scene_character_action *FirstCharacterAction; scene_character_action *LastCharacterAction; branch_case *FirstBranchCase; scene_runtime_result LastResult; }; //////////////////////////////// //~ sixten: Scene Compiler Functions //- sixten: value helpers inline scene_value S_MakeNil(void) { scene_value Result; Result.Kind = S_ValueKind_Nil; return(Result); } 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); } inline scene_value S_MakeSourceRef(token Token) { scene_value Result; Result.Kind = S_ValueKind_SourceRef; Result.SourceRef = Token.Range; return(Result); } inline scene_value S_MakeOffset(s64 Offset) { scene_value Result; Result.Kind = S_ValueKind_Offset; Result.Offset = Offset; return(Result); } //- sixten: error messaging static void S_ParseError(scene_compiler *Compiler, char *Message, s64 TokenOffset = -1); //- sixten: bytecode helpers static void S_EmitByte(scene_compiler *Compiler, u8 Byte); static void S_EmitU32(scene_compiler *Compiler, u32 Value); static void S_EmitBucket(scene_compiler *Compiler, scene_annotated_bytecode_bucket *Bucket); static u64 S_MakeConstant(scene_compiler *Compiler, scene_value Value); static void S_EmitConstant(scene_compiler *Compiler, scene_value Value); static void S_SetEmissionTarget(scene_compiler *Compiler, scene_emission_target Target); static void S_PushEmissionTarget(scene_compiler *Compiler, scene_emission_target Target); static void S_PopEmissionTarget(scene_compiler *Compiler); static scene_annotated_bytecode_chunk *S_FindBytecodeChunkByName(scene_compiler *Compiler, string Name); inline scene_emission_target S_RawEmissionTarget(memory_arena *Arena, scene_annotated_bytecode_bucket *Bucket) { scene_emission_target Target = {}; Target.Arena = Arena; Target.Bucket = Bucket; Target.Type = S_EmissionTarget_Raw; return(Target); } inline scene_emission_target S_NamedEmissionTarget(memory_arena *Arena, scene_annotated_bytecode_bucket *Bucket, string Name) { scene_emission_target Target = {}; Target.Arena = Arena; Target.Bucket = Bucket; Target.Type = S_EmissionTarget_Named; Target.Name = Name; return(Target); } //- 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_ParseJumpStatement(scene_compiler *Compiler); static void S_ParseBranchStatement(scene_compiler *Compiler); static scene_branch_case *S_ParseBranchCase(scene_compiler *Compiler, memory_arena *Arena); 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_ParseString(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: compilation static compiled_scene S_ScriptFromText(memory_arena *Arena, string Text); static compiled_scene S_CopyCompiledScene(memory_arena *Arena, compiled_scene *Compiled); //////////////////////////////// //~ sixten: Scene Runtime Functions static scene_proc *S_FindProcByName(compiled_scene *Compiled, string Name); static void S_ResetRuntime(scene_runtime *Runtime); static scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameArena, b32 AdvanceOnAwait); #endif //VN_SCENE_H