459 lines
9.9 KiB
C
459 lines
9.9 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;
|
|
};
|
|
|
|
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;
|
|
string Name;
|
|
s64 Count;
|
|
u8 Data[4096];
|
|
};
|
|
|
|
struct scene_bytecode_bucket
|
|
{
|
|
scene_bytecode_chunk *First;
|
|
scene_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
|
|
{
|
|
arena *Arena;
|
|
scene_bytecode_bucket *Bucket;
|
|
scene_emission_target_type Type;
|
|
string Name;
|
|
};
|
|
|
|
struct scene_branch_case
|
|
{
|
|
scene_branch_case *Next;
|
|
token Name;
|
|
scene_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
|
|
{
|
|
arena *Arena;
|
|
|
|
b32 InPanicMode;
|
|
b32 EncounteredError;
|
|
scene_compile_error_list Errors;
|
|
|
|
string Text;
|
|
token *TokensBegin;
|
|
token *TokensEnd;
|
|
token *At;
|
|
|
|
scene_bytecode_bucket GlobalScope;
|
|
scene_bytecode_bucket ProcBuckets[32];
|
|
|
|
scene_emission_target TargetStack[16];
|
|
s32 TargetStackIndex;
|
|
|
|
scene_value_chunk *FirstValueChunk;
|
|
scene_value_chunk *LastValueChunk;
|
|
s64 ValueCount;
|
|
|
|
string NavFileName;
|
|
asset_id BackgroundTexture;
|
|
};
|
|
|
|
////////////////////////////////
|
|
//~ 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 *GlobalScope;
|
|
scene_proc_bucket Buckets[16];
|
|
scene_value *Values;
|
|
s64 ValueCount;
|
|
string Source;
|
|
string NavFileName;
|
|
asset_id BackgroundTexture;
|
|
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_error_list
|
|
{
|
|
scene_runtime_error *First;
|
|
scene_runtime_error *Last;
|
|
s64 Count;
|
|
};
|
|
|
|
struct scene_named_value
|
|
{
|
|
b32 Initialized;
|
|
string Name;
|
|
scene_value Value;
|
|
};
|
|
|
|
struct scene_named_value_node
|
|
{
|
|
scene_named_value_node *Next;
|
|
scene_named_value_node *Prev;
|
|
scene_named_value NamedValue;
|
|
};
|
|
|
|
struct scene_named_value_bucket
|
|
{
|
|
s64 Count;
|
|
scene_named_value_node *First;
|
|
scene_named_value_node *Last;
|
|
};
|
|
|
|
struct scene_runtime_result
|
|
{
|
|
b32 HadError;
|
|
b32 ReachedAwait;
|
|
};
|
|
|
|
enum scene_textbox_action_kind
|
|
{
|
|
S_TextboxActionKind_Set,
|
|
S_TextboxActionKind_Append,
|
|
};
|
|
|
|
struct scene_textbox_action
|
|
{
|
|
scene_textbox_action *Next;
|
|
scene_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
|
|
arena *RuntimeArena;
|
|
scene_proc *CurrentProc;
|
|
s64 IP;
|
|
scene_runtime_stack Stack;
|
|
scene_named_value_bucket GlobalVariableBuckets[16];
|
|
scene_named_value_bucket GlobalVariableFreeList;
|
|
|
|
// sixten: errors
|
|
arena *ErrorArena;
|
|
scene_runtime_error_list Errors;
|
|
|
|
// sixten: branches
|
|
branch_case Branches[16];
|
|
s64 BranchCount;
|
|
|
|
// sixten: result
|
|
scene_runtime_result LastResult;
|
|
scene_textbox_action *FirstTextboxAction;
|
|
scene_textbox_action *LastTextboxAction;
|
|
scene_character_action *FirstCharacterAction;
|
|
scene_character_action *LastCharacterAction;
|
|
};
|
|
|
|
////////////////////////////////
|
|
//~ 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_MakeSourceRef(range1_s64 Range)
|
|
{
|
|
scene_value Result;
|
|
Result.Kind = S_ValueKind_SourceRef;
|
|
Result.SourceRef = 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_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);
|
|
|
|
inline scene_emission_target S_RawEmissionTarget(arena *Arena, scene_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(arena *Arena, scene_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 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_ParseNavFilePath(scene_compiler *Compiler);
|
|
static void S_ParseBackgroundAsset(scene_compiler *Compiler);
|
|
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, 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_bytecode_chunk *Chunk, arena *Arena);
|
|
|
|
//- sixten: compilation
|
|
static compiled_scene S_ScriptFromText(arena *Arena, string Text);
|
|
static compiled_scene S_CopyCompiledScene(arena *Arena, compiled_scene *Compiled);
|
|
|
|
////////////////////////////////
|
|
//~ sixten: Scene Runtime Functions
|
|
static scene_proc *S_FindProcByName(compiled_scene *Compiled, string Name);
|
|
static scene_named_value *S_FindGlobalVariableByName(scene_runtime *Runtime, string Name, b32 AlwaysCreate = true);
|
|
static void S_ResetRuntime(scene_runtime *Runtime);
|
|
static scene_runtime_result S_Run(scene_runtime *Runtime, arena *Arena, b32 AdvanceOnAwait);
|
|
|
|
#endif //VN_SCENE_H
|