vn/code/vn_scene.h

429 lines
10 KiB
C

/* 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;
};
typedef u64 scene_line_entry_flag;
enum
{
S_LineEntryFlag_NoClear = (1<<0),
};
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_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_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;
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
{
string Name;
scene_character *Next;
scene_character *Prev;
};
struct scene_character_bucket
{
scene_character *First;
scene_character *Last;
s64 Count;
};
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
scene_proc *CurrentProc;
s64 IP;
memory_arena *Arena;
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;
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 scene_runtime_result S_Run(scene_runtime *Runtime, memory_arena *FrameArena, b32 AdvanceOnAwait);
#endif //VN_SCENE_H