diff --git a/lib/pinc_bytecode/bytecode.ml b/lib/pinc_bytecode/bytecode.ml index e962780..163320b 100644 --- a/lib/pinc_bytecode/bytecode.ml +++ b/lib/pinc_bytecode/bytecode.ml @@ -1,6 +1,6 @@ type t = { instructions : Instruction.t Array.t; - constants : Value.t Int32.Map.t; + constants : Value.t Dynarray.t; } let make ~instructions ~constants = { instructions; constants } @@ -40,33 +40,37 @@ and pp_function fmt fn = ;; let pp_constants fmt constants = - Int32.Map.iter - (fun key value -> Format.fprintf fmt "@[%a : %a@;@]" Int32.pp key pp_value value) + Dynarray.iteri + (fun key value -> + Format.fprintf fmt "@[0x%08X (%08i) : %a@;@]" key key pp_value value) constants ;; let pp fmt t = - if not @@ Int32.Map.is_empty t.constants then ( - Format.fprintf Format.std_formatter "[CONSTANTS]@."; - pp_constants fmt t.constants; - Format.fprintf Format.std_formatter "@."); - - if Array.length t.instructions > 0 then ( - Format.fprintf Format.std_formatter "[INSTRUCTIONS]@."; - Format.fprintf fmt "@[%a@]" pp_instructions t.instructions) + let () = + match Dynarray.is_empty t.constants with + | true -> () + | false -> + Format.fprintf Format.std_formatter "[CONSTANTS]@."; + pp_constants fmt t.constants; + Format.fprintf Format.std_formatter "@." + in + let () = + match t.instructions with + | [||] -> () + | instructions -> + Format.fprintf Format.std_formatter "[INSTRUCTIONS]@."; + Format.fprintf fmt "@[%a@]" pp_instructions instructions + in + () ;; let serialize t = let buf = Buffer.create 65565 in let constants = t.constants in - let num_constants = Int32.Map.cardinal constants in + let num_constants = Dynarray.length constants in Buffer.add_int32_be buf @@ Int32.of_int num_constants; - let () = - constants - |> Int32.Map.iter (fun key value -> - Buffer.add_int32_be buf key; - Value.serialize buf value) - in + let () = constants |> Dynarray.iter (Value.serialize buf) in let () = Buffer.add_int32_be buf @@ Int32.of_int (Array.length t.instructions) in let () = Array.iter @@ -84,12 +88,7 @@ let deserialize ?(function_count = ref 0) str = let num_constants = Int32.to_int @@ Bytes.get_int32_be bytes !offset in offset := !offset + 4; let constants = - Int32.Map.of_seq - @@ Seq.init num_constants (fun _ -> - let key = Bytes.get_int32_be bytes !offset in - offset := !offset + 4; - let value = Value.deserialize ~function_count bytes offset in - (key, value)) + Dynarray.init num_constants @@ fun _ -> Value.deserialize ~function_count bytes offset in let instructions_length = Int32.to_int @@ Bytes.get_int32_be bytes !offset in offset := !offset + 4; diff --git a/lib/pinc_bytecode/externals.ml b/lib/pinc_bytecode/externals.ml index a81ae46..174ab57 100644 --- a/lib/pinc_bytecode/externals.ml +++ b/lib/pinc_bytecode/externals.ml @@ -2,8 +2,8 @@ module PincArray = struct let length ~arguments = let array = match arguments with - | [ Value.Array a ] -> a - | [ _ ] -> + | [| Value.Array a |] -> a + | [| _ |] -> raise_notrace (Invalid_argument "The argument given to the Array.length function is not of type array") @@ -22,8 +22,8 @@ module PincString = struct let length ~arguments = let string = match arguments with - | [ Value.String a ] -> a - | [ _ ] -> + | [| Value.String a |] -> a + | [| _ |] -> raise_notrace (Invalid_argument "The argument given to the String.length function is not of type string") @@ -40,17 +40,17 @@ module PincString = struct let sub ~arguments = let string, offset, length = match arguments with - | [ Value.String string; Value.Int offset; Value.Int length ] -> + | [| Value.String string; Value.Int offset; Value.Int length |] -> (string, offset, length) - | [ _; Value.Int _; Value.Int _ ] -> + | [| _; Value.Int _; Value.Int _ |] -> raise_notrace (Invalid_argument "The first argument given to `String.sub` is not of type string") - | [ Value.String _; _; Value.Int _ ] -> + | [| Value.String _; _; Value.Int _ |] -> raise_notrace (Invalid_argument "The second argument (offset) given to `String.sub` is not of type int") - | [ Value.String _; Value.Int _; _ ] -> + | [| Value.String _; Value.Int _; _ |] -> raise_notrace (Invalid_argument "The third argument (length) given to `String.sub` is not of type int") diff --git a/lib/pinc_bytecode/instruction.ml b/lib/pinc_bytecode/instruction.ml index bdf6004..9b35d02 100644 --- a/lib/pinc_bytecode/instruction.ml +++ b/lib/pinc_bytecode/instruction.ml @@ -1,7 +1,7 @@ type t = | I_Null | I_Pop - | I_Constant of Int32.t + | I_Constant of int | I_Add | I_Sub | I_Div @@ -20,26 +20,26 @@ type t = | I_Or | I_Minus | I_Not - | I_Jump of Int32.t - | I_Jump_If_False of Int32.t - | I_Set_Global of Int32.t - | I_Get_Global of Int32.t + | I_Jump of int + | I_Jump_If_False of int + | I_Set_Global of int + | I_Get_Global of int | I_Concat | I_Dynamic_Array - | I_Array of Int32.t - | I_Record of Int32.t + | I_Array of int + | I_Record of int | I_Index | I_Dot_Index | I_Range | I_Range_Inclusive - | I_Call of Int32.t + | I_Call of int | I_Return - | I_Set_Local of Int32.t - | I_Get_Local of Int32.t + | I_Set_Local of int + | I_Get_Local of int | I_Length - | I_Get_Builtin of Int32.t - | I_Closure of (Int32.t * Int32.t) - | I_Get_Free of Int32.t + | I_Get_Builtin of int + | I_Closure of (int * int) + | I_Get_Free of int | I_Current_Closure | I_Halt | I_Debug_Print_Stack @@ -147,7 +147,7 @@ let decode bytes offset = | 0x00 -> (offset, I_Pop) | 0x01 -> let offset, addr = Int32.read_bytes bytes offset in - (offset, I_Constant addr) + (offset, I_Constant (Int32.to_int addr)) | 0x02 -> (offset, I_Add) | 0x03 -> (offset, I_Sub) | 0x04 -> (offset, I_Div) @@ -168,50 +168,50 @@ let decode bytes offset = | 0x13 -> (offset, I_Not) | 0x14 -> let offset, addr = Int32.read_bytes bytes offset in - (offset, I_Jump addr) + (offset, I_Jump (Int32.to_int addr)) | 0x15 -> let offset, addr = Int32.read_bytes bytes offset in - (offset, I_Jump_If_False addr) + (offset, I_Jump_If_False (Int32.to_int addr)) | 0x16 -> (offset, I_Null) | 0x17 -> let offset, addr = Int32.read_bytes bytes offset in - (offset, I_Set_Global addr) + (offset, I_Set_Global (Int32.to_int addr)) | 0x18 -> let offset, addr = Int32.read_bytes bytes offset in - (offset, I_Get_Global addr) + (offset, I_Get_Global (Int32.to_int addr)) | 0x19 -> (offset, I_Concat) | 0x1A -> let offset, length = Int32.read_bytes bytes offset in - (offset, I_Array length) + (offset, I_Array (Int32.to_int length)) | 0x1B -> let offset, length = Int32.read_bytes bytes offset in - (offset, I_Record length) + (offset, I_Record (Int32.to_int length)) | 0x1C -> (offset, I_Index) | 0x1D -> (offset, I_Dot_Index) | 0x1E -> (offset, I_Range) | 0x1F -> (offset, I_Range_Inclusive) | 0x20 -> let offset, arguments = Int32.read_bytes bytes offset in - (offset, I_Call arguments) + (offset, I_Call (Int32.to_int arguments)) | 0x21 -> (offset, I_Return) | 0x22 -> let offset, addr = Int32.read_bytes bytes offset in - (offset, I_Set_Local addr) + (offset, I_Set_Local (Int32.to_int addr)) | 0x23 -> let offset, addr = Int32.read_bytes bytes offset in - (offset, I_Get_Local addr) + (offset, I_Get_Local (Int32.to_int addr)) | 0x24 -> (offset, I_Length) | 0x25 -> (offset, I_Dynamic_Array) | 0x26 -> let offset, addr = Int32.read_bytes bytes offset in - (offset, I_Get_Builtin addr) + (offset, I_Get_Builtin (Int32.to_int addr)) | 0x27 -> let offset, fn_addr = Int32.read_bytes bytes offset in let offset, free_variables = Int32.read_bytes bytes offset in - (offset, I_Closure (fn_addr, free_variables)) + (offset, I_Closure (Int32.to_int fn_addr, Int32.to_int free_variables)) | 0x28 -> let offset, addr = Int32.read_bytes bytes offset in - (offset, I_Get_Free addr) + (offset, I_Get_Free (Int32.to_int addr)) | 0x29 -> (offset, I_Current_Closure) | 0x2A -> (offset, I_Halt) | 0xFF -> (offset, I_Debug_Print_Stack) @@ -222,7 +222,7 @@ let decode bytes offset = let pp fmt = function | I_Pop -> Format.fprintf fmt "I_Pop" - | I_Constant addr -> Format.fprintf fmt "I_Constant %a" Int32.pp addr + | I_Constant addr -> Format.fprintf fmt "I_Constant 0x%08X (%08i)" addr addr | I_Add -> Format.fprintf fmt "I_Add" | I_Sub -> Format.fprintf fmt "I_Sub" | I_Div -> Format.fprintf fmt "I_Div" @@ -241,33 +241,33 @@ let pp fmt = function | I_Or -> Format.fprintf fmt "I_Or" | I_Minus -> Format.fprintf fmt "I_Minus" | I_Not -> Format.fprintf fmt "I_Not" - | I_Jump addr -> Format.fprintf fmt "I_Jump %a" Int32.pp addr - | I_Jump_If_False addr -> Format.fprintf fmt "I_Jump_If_False %a" Int32.pp addr + | I_Jump addr -> Format.fprintf fmt "I_Jump 0x%08X (%08i)" addr addr + | I_Jump_If_False addr -> Format.fprintf fmt "I_Jump_If_False 0x%08X (%08i)" addr addr | I_Null -> Format.fprintf fmt "I_Null" - | I_Get_Global addr -> Format.fprintf fmt "I_Get_Global %a" Int32.pp addr - | I_Set_Global addr -> Format.fprintf fmt "I_Set_Global %a" Int32.pp addr - | I_Array length -> Format.fprintf fmt "I_Array %i" (Int32.to_int length) + | I_Get_Global addr -> Format.fprintf fmt "I_Get_Global 0x%08X (%08i)" addr addr + | I_Set_Global addr -> Format.fprintf fmt "I_Set_Global 0x%08X (%08i)" addr addr + | I_Array length -> Format.fprintf fmt "I_Array %i" length | I_Concat -> Format.fprintf fmt "I_Concat" - | I_Record length -> Format.fprintf fmt "I_Record %i" (Int32.to_int length) + | I_Record length -> Format.fprintf fmt "I_Record %i" length | I_Index -> Format.fprintf fmt "I_Index" | I_Dot_Index -> Format.fprintf fmt "I_Dot_Index" | I_Range -> Format.fprintf fmt "I_Range" | I_Range_Inclusive -> Format.fprintf fmt "I_Range_Inclusive" - | I_Call arguments -> Format.fprintf fmt "I_Call %li" arguments + | I_Call arguments -> Format.fprintf fmt "I_Call %i" arguments | I_Return -> Format.fprintf fmt "I_Return" - | I_Get_Local addr -> Format.fprintf fmt "I_Get_Local %a" Int32.pp addr - | I_Set_Local addr -> Format.fprintf fmt "I_Set_Local %a" Int32.pp addr + | I_Get_Local addr -> Format.fprintf fmt "I_Get_Local 0x%08X (%08i)" addr addr + | I_Set_Local addr -> Format.fprintf fmt "I_Set_Local 0x%08X (%08i)" addr addr | I_Length -> Format.fprintf fmt "I_Length" | I_Dynamic_Array -> Format.fprintf fmt "I_Dynamic_Array" - | I_Get_Builtin addr -> Format.fprintf fmt "I_Get_Builtin %a" Int32.pp addr - | I_Get_Free addr -> Format.fprintf fmt "I_Get_Free %a" Int32.pp addr + | I_Get_Builtin addr -> Format.fprintf fmt "I_Get_Builtin 0x%08X (%08i)" addr addr + | I_Get_Free addr -> Format.fprintf fmt "I_Get_Free 0x%08X (%08i)" addr addr | I_Closure (fn_addr, free_variables) -> Format.fprintf fmt - "I_Closure %a (free variables: %i)" - Int32.pp + "I_Closure 0x%08X (%08i) (free variables: %i)" fn_addr - (Int32.to_int free_variables) + fn_addr + free_variables | I_Current_Closure -> Format.fprintf fmt "I_Current_Closure" | I_Halt -> Format.fprintf fmt "I_Halt" | I_Debug_Print_Stack -> Format.fprintf fmt "I_Debug_Print_Stack" @@ -296,10 +296,10 @@ let to_bytes t = | I_Get_Local op | I_Get_Builtin op | I_Get_Free op - | I_Call op -> offset := Int32.write_bytes bytes !offset op + | I_Call op -> offset := Int32.write_bytes bytes !offset @@ Int32.of_int op | I_Closure (op1, op2) -> - offset := Int32.write_bytes bytes !offset op1; - offset := Int32.write_bytes bytes !offset op2 + offset := Int32.write_bytes bytes !offset @@ Int32.of_int op1; + offset := Int32.write_bytes bytes !offset @@ Int32.of_int op2 | I_Pop | I_Add | I_Sub diff --git a/lib/pinc_bytecode/value.ml b/lib/pinc_bytecode/value.ml index 1f60120..4f87235 100644 --- a/lib/pinc_bytecode/value.ml +++ b/lib/pinc_bytecode/value.ml @@ -25,7 +25,7 @@ and compiled_function = { and closure = { fn : compiled_function; - free_variables : t Int32.Map.t; + free_variables : t Array.t; } let pp fmt = function @@ -106,7 +106,7 @@ let rec equal a b = | Record a, Record b -> StringMap.equal equal a b | Function a, Function b -> equal_function a b | Closure a, Closure b -> - Int32.Map.equal equal a.free_variables b.free_variables && equal_function a.fn b.fn + Array.equal equal a.free_variables b.free_variables && equal_function a.fn b.fn | BuiltinFunction a, BuiltinFunction b -> Int.equal a.num_parameters b.num_parameters && Int.equal a.fn_index b.fn_index | _ -> false @@ -199,14 +199,10 @@ and serialize_builtin_function buf f = and serialize_closure buf c = let fn = c.fn in let free_variables = c.free_variables in - let num_free_variables = Int32.Map.cardinal free_variables in + let num_free_variables = Array.length free_variables in Buffer.add_int8 buf 0x0B; Buffer.add_int32_be buf @@ Int32.of_int num_free_variables; - Int32.Map.iter - (fun key value -> - Buffer.add_int32_be buf key; - serialize buf value) - free_variables; + Array.iter (serialize buf) free_variables; serialize_function buf fn ;; @@ -285,12 +281,7 @@ let deserialize ~function_count bytes offset = let num_free_variables = Int32.to_int @@ Bytes.get_int32_be bytes !offset in offset := !offset + 4; let free_variables = - Int32.Map.of_list - @@ List.init num_free_variables (fun _ -> - let key = Bytes.get_int32_be bytes !offset in - offset := !offset + 4; - let value = deserialize_value bytes offset in - (key, value)) + Array.init num_free_variables @@ fun _ -> deserialize_value bytes offset in let fn = deserialize_function bytes offset in { free_variables; fn } diff --git a/lib/pinc_compiler/compiler.ml b/lib/pinc_compiler/compiler.ml index 32645b7..7cc951e 100644 --- a/lib/pinc_compiler/compiler.ml +++ b/lib/pinc_compiler/compiler.ml @@ -12,7 +12,7 @@ type scope = { } type t = { - constants : Pinc_Bytecode.Value.t Int32.Map.t; + constants : Pinc_Bytecode.Value.t Dynarray.t; symbol_table : SymbolTable.t; scopes : scope list; } @@ -98,16 +98,10 @@ let pop_scope t = ({ t with scopes; symbol_table = SymbolTable.pop_scope t.symbol_table }, scope) ;; -let make_constant_id = - let id' = ref Int32.minus_one in - fun () -> - id' := Int32.succ !id'; - !id' -;; - -let add_constant ?(id = make_constant_id ()) t constant = - let constants = Int32.Map.add id constant t.constants in - (id, { t with constants }) +let add_constant t constant = + let () = Dynarray.add_last t.constants constant in + let id = Dynarray.length t.constants - 1 in + (id, t) ;; let emit t opcode = @@ -220,13 +214,13 @@ let rec compile_expr t (expr : Pinc_Types.Ast.expression) = ^ " parameters, but got " ^ string_of_int parameters) else - emit t @@ Pinc_Bytecode.Instruction.I_Get_Builtin (Int32.of_int index) + emit t @@ Pinc_Bytecode.Instruction.I_Get_Builtin index in t | UppercaseIdentifierExpression _ -> raise_notrace TODO | Array a -> let t = Array.fold_left compile_expr t a in - emit t @@ Pinc_Bytecode.Instruction.I_Array (Int32.of_int @@ Array.length a) + emit t @@ Pinc_Bytecode.Instruction.I_Array (Array.length a) | Record map -> let bindings = StringMap.bindings map in let keys, values = List.split bindings in @@ -234,7 +228,7 @@ let rec compile_expr t (expr : Pinc_Types.Ast.expression) = let t = List.fold_left emit_key t keys in let emit_value t (_, expr) = compile_expr t expr in let t = List.fold_left emit_value t values in - let length = Int32.of_int @@ List.length keys in + let length = List.length keys in let t = emit t @@ Pinc_Bytecode.Instruction.I_Record length in t | Function { identifier; parameters; body } -> @@ -289,14 +283,13 @@ let rec compile_expr t (expr : Pinc_Types.Ast.expression) = { fn_addr = -1; num_locals; num_parameters; instructions } in let t = - emit t - @@ Pinc_Bytecode.Instruction.I_Closure (fn_addr, Int32.of_int num_free_variables) + emit t @@ Pinc_Bytecode.Instruction.I_Closure (fn_addr, num_free_variables) in t | FunctionCall { function_definition; arguments } -> let t = compile_expr t function_definition in let t = List.fold_left compile_expr t arguments in - let num_arguments = Int32.of_int @@ List.length arguments in + let num_arguments = List.length arguments in let t = emit t @@ Pinc_Bytecode.Instruction.I_Call num_arguments in t | TagExpression _ -> raise_notrace TODO @@ -410,7 +403,7 @@ and compile_conditional_expression t ~condition ~consequent ~alternate = (* Consequent *) (* We create a conditional jump with a temporary address first, because we do not know where we should jump to next. *) - let t = emit t (Pinc_Bytecode.Instruction.I_Jump_If_False 0xFFFFFFFl) in + let t = emit t (Pinc_Bytecode.Instruction.I_Jump_If_False 0xFFFFFFF) in let jump_consequent_offset = last_instruction_offset t in let t = compile_expr t consequent in let t = @@ -421,9 +414,9 @@ and compile_conditional_expression t ~condition ~consequent ~alternate = in (* Alternate *) - let t = emit t (Pinc_Bytecode.Instruction.I_Jump 0xFFFFFFFl) in + let t = emit t (Pinc_Bytecode.Instruction.I_Jump 0xFFFFFFF) in let jump_alternate_offset = last_instruction_offset t in - let jump_address = Int32.of_int (Dynarray.length @@ current_instructions t) in + let jump_address = Dynarray.length @@ current_instructions t in let t = replace_instruction t jump_consequent_offset @@ Pinc_Bytecode.Instruction.I_Jump_If_False jump_address @@ -441,7 +434,7 @@ and compile_conditional_expression t ~condition ~consequent ~alternate = in t in - let jump_address = Int32.of_int (Dynarray.length @@ current_instructions t) in + let jump_address = Dynarray.length @@ current_instructions t in let t = replace_instruction t jump_alternate_offset @@ Pinc_Bytecode.Instruction.I_Jump jump_address @@ -470,7 +463,7 @@ and compile_loop_expression t ~index ~iterator ~reverse:_ ~iterable ~body = let t = emit t @@ Pinc_Bytecode.Instruction.I_Length in let t = emit_set_symbol t length_symbol in (* Set Iterator *) - let jump_address = Int32.of_int (Dynarray.length @@ current_instructions t) in + let jump_address = Dynarray.length @@ current_instructions t in let t = emit_get_symbol t iterable_symbol in let t = emit_get_symbol t index_symbol in let t = emit t @@ Pinc_Bytecode.Instruction.I_Index in @@ -528,20 +521,19 @@ let compile_declaration (decl : Pinc_Types.Ast.declaration) t = ;; let compile (ast : Pinc_Types.Ast.t) = - let scope = - { - instructions = Dynarray.create (); - previous_instruction = empty_instruction; - last_instruction = empty_instruction; - } - in - let t = - { - constants = Int32.Map.empty; - symbol_table = SymbolTable.make (); - scopes = [ scope ]; - } + let scopes = + [ + { + instructions = Dynarray.create (); + previous_instruction = empty_instruction; + last_instruction = empty_instruction; + }; + ] in + let constants = Dynarray.create () in + let () = Dynarray.ensure_capacity constants 2048 in + let symbol_table = SymbolTable.make () in + let t = { constants; symbol_table; scopes } in let t = StringMap.fold (fun _ -> compile_declaration) ast t in Pinc_Bytecode.Bytecode.serialize diff --git a/lib/pinc_core/StdlibExtension.ml b/lib/pinc_core/StdlibExtension.ml index 8dea7a1..07be403 100644 --- a/lib/pinc_core/StdlibExtension.ml +++ b/lib/pinc_core/StdlibExtension.ml @@ -212,6 +212,4 @@ module Int32 = struct ;; let pp fmt t = Format.fprintf fmt "0x%08lX (%08li)" t t - - module Map = Map.Make (Int32) end diff --git a/lib/pinc_core/SymbolTable.ml b/lib/pinc_core/SymbolTable.ml index a7df065..4c30c9c 100644 --- a/lib/pinc_core/SymbolTable.ml +++ b/lib/pinc_core/SymbolTable.ml @@ -10,7 +10,7 @@ module Symbol = struct type t = { name : string; scope : Scope.t; - address : Int32.t; + address : int; } let make ~name ~scope ~address = { name; scope; address } @@ -22,17 +22,12 @@ end type t = { store : Symbol.t StringMap.t; free_variables : Symbol.t list; - num_bindings : Int32.t; + num_bindings : int; outer : t option; } let make () = - { - store = StringMap.empty; - free_variables = []; - num_bindings = Int32.zero; - outer = None; - } + { store = StringMap.empty; free_variables = []; num_bindings = 0; outer = None } ;; let add_scope t = @@ -57,7 +52,7 @@ let define_symbol t ~name = { t with store = StringMap.add name symbol t.store; - num_bindings = Int32.succ t.num_bindings; + num_bindings = Int.succ t.num_bindings; } in (t', symbol) @@ -66,7 +61,7 @@ let define_symbol t ~name = let define_free_symbol t symbol = let name = Symbol.name symbol in let free_symbol = - Symbol.make ~name ~scope:Free ~address:(Int32.of_int @@ List.length t.free_variables) + Symbol.make ~name ~scope:Free ~address:(List.length t.free_variables) in let t' = { @@ -79,7 +74,7 @@ let define_free_symbol t symbol = ;; let define_function_symbol t ~name = - let symbol = Symbol.make ~name ~scope:Function ~address:0l in + let symbol = Symbol.make ~name ~scope:Function ~address:0 in let t' = { t with store = StringMap.add name symbol t.store } in (t', symbol) ;; @@ -103,4 +98,4 @@ let rec resolve_symbol t ~name = ;; let free_variables t = t.free_variables -let length t = Int32.to_int t.num_bindings +let length t = t.num_bindings diff --git a/lib/pinc_vm/vm.ml b/lib/pinc_vm/vm.ml index 817ba09..af4e26a 100644 --- a/lib/pinc_vm/vm.ml +++ b/lib/pinc_vm/vm.ml @@ -8,10 +8,10 @@ let stack_size = 2048 type t = { stack : Vm_stack.t; resolved_functions : (t -> t) Array.t Array.t; - globals : Value.t Int32.Map.t; + globals : Value.t Array.t; past_frames : frame list; current_frame : frame; - constants : Value.t Int32.Map.t; + constants : Value.t Array.t; } and frame = { @@ -72,7 +72,7 @@ let make ~constants ~resolved_functions ~instructions = num_parameters = 0; instructions = [||]; }; - free_variables = Int32.Map.empty; + free_variables = [||]; } in let main_frame = make_frame ~base_pointer:0 ~closure in @@ -80,7 +80,7 @@ let make ~constants ~resolved_functions ~instructions = constants; resolved_functions; stack = Stack.make ~size:stack_size; - globals = Int32.Map.empty; + globals = Array.make 131_072 Value.Null; past_frames = []; current_frame = main_frame; } @@ -702,22 +702,21 @@ let execute_unary_not t = ;; let rec execute_function_call num_arguments = - let num_arguments = Int32.to_int num_arguments in - fun t -> - let fn = Stack.nth t.stack num_arguments in - match fn with - | Value.Closure { fn = { num_parameters; _ }; _ } - | Value.BuiltinFunction { num_parameters; _ } - when not @@ Int.equal num_parameters num_arguments -> - raise_notrace - @@ Invalid_argument - ("Trying to call a function with the wrong number of arguments. Wanted " - ^ string_of_int num_parameters - ^ ", got " - ^ string_of_int num_arguments) - | Value.Closure closure -> call_closure t ~closure ~num_arguments - | Value.BuiltinFunction { fn_index; _ } -> call_builtin t ~fn_index ~num_arguments - | _ -> raise_notrace @@ Invalid_argument "Trying to call a non function value" + fun t -> + let fn = Stack.nth t.stack num_arguments in + match fn with + | Value.Closure { fn = { num_parameters; _ }; _ } + | Value.BuiltinFunction { num_parameters; _ } + when not @@ Int.equal num_parameters num_arguments -> + raise_notrace + @@ Invalid_argument + ("Trying to call a function with the wrong number of arguments. Wanted " + ^ string_of_int num_parameters + ^ ", got " + ^ string_of_int num_arguments) + | Value.Closure closure -> call_closure t ~closure ~num_arguments + | Value.BuiltinFunction { fn_index; _ } -> call_builtin t ~fn_index ~num_arguments + | _ -> raise_notrace @@ Invalid_argument "Trying to call a non function value" and call_builtin ~fn_index ~num_arguments t = let arguments = Stack.pop_n t.stack num_arguments in @@ -764,7 +763,7 @@ let execute_pop t = let execute_constant addr = fun t -> - let constant = Int32.Map.find addr t.constants in + let constant = Array.get t.constants addr in Stack.push_value t.stack constant; call_next_instruction t ;; @@ -785,49 +784,46 @@ let execute_null t = ;; let execute_jump addr = - let addr = Int32.to_int addr in - fun t -> - let t = set_instruction_pointer t addr in - call_current_instruction t + fun t -> + let t = set_instruction_pointer t addr in + call_current_instruction t ;; let execute_jump_if_false addr = - let addr = Int32.to_int addr in - fun t -> - let condition_tag = Stack.peek_tag t.stack 0 in - let is_false = - match condition_tag with - | Tag_Bool -> not @@ Stack.pop_bool t.stack - | Tag_Null -> - Stack.drop t.stack; - true - | _ -> - let condition = Stack.pop_value t.stack in - not @@ Value.is_true condition - in - if is_false then ( - let t = set_instruction_pointer t addr in - call_current_instruction t) - else - call_next_instruction t + fun t -> + let condition_tag = Stack.peek_tag t.stack 0 in + let is_false = + match condition_tag with + | Tag_Bool -> not @@ Stack.pop_bool t.stack + | Tag_Null -> + Stack.drop t.stack; + true + | _ -> + let condition = Stack.pop_value t.stack in + not @@ Value.is_true condition + in + if is_false then ( + let t = set_instruction_pointer t addr in + call_current_instruction t) + else + call_next_instruction t ;; let execute_set_global addr = fun t -> let value = Stack.pop_value t.stack in - let t = { t with globals = Int32.Map.add addr value t.globals } in + Array.set t.globals addr value; call_next_instruction t ;; let execute_get_global addr = fun t -> - let value = Int32.Map.find addr t.globals in + let value = Array.get t.globals addr in Stack.push_value t.stack value; call_next_instruction t ;; -let execute_get_builtin addr = - let fn_index = Int32.to_int addr in +let execute_get_builtin fn_index = let num_parameters = Pinc_Bytecode.Externals.expected_parameters fn_index in let value = Value.BuiltinFunction { num_parameters; fn_index } in fun t -> @@ -837,27 +833,25 @@ let execute_get_builtin addr = let execute_get_free addr = fun t -> - let value = Int32.Map.find addr (frame_free_variables (current_frame t)) in + let value = Array.get (frame_free_variables (current_frame t)) addr in Stack.push_value t.stack value; call_next_instruction t ;; let execute_set_local addr = - let addr = Int32.to_int addr in - fun t -> - let frame = current_frame t in - let addr = frame.base_pointer + addr in - let () = Stack.move_from_top t.stack addr in - call_next_instruction t + fun t -> + let frame = current_frame t in + let addr = frame.base_pointer + addr in + let () = Stack.move_from_top t.stack addr in + call_next_instruction t ;; let execute_get_local addr = - let addr = Int32.to_int addr in - fun t -> - let frame = current_frame t in - let address = frame.base_pointer + addr in - let () = Stack.copy_to_top t.stack address in - call_next_instruction t + fun t -> + let frame = current_frame t in + let address = frame.base_pointer + addr in + let () = Stack.copy_to_top t.stack address in + call_next_instruction t ;; let execute_dynamic_array t = @@ -866,35 +860,34 @@ let execute_dynamic_array t = | Tag_Int -> Stack.pop_int t.stack | _ -> assert false in - let elements = Array.of_list @@ Stack.pop_n t.stack length in + let elements = Stack.pop_n t.stack length in let value = Value.Array elements in Stack.push_value t.stack value; call_next_instruction t ;; let execute_array length = - let length = Int32.to_int length in - fun t -> - let elements = Array.of_list @@ Stack.pop_n t.stack length in - let value = Value.Array elements in - Stack.push_value t.stack value; - call_next_instruction t + fun t -> + let elements = Stack.pop_n t.stack length in + let value = Value.Array elements in + Stack.push_value t.stack value; + call_next_instruction t ;; let execute_record length = - let int_length = Int32.to_int length in - fun t -> - let values = Stack.pop_n t.stack int_length in - let keys = - Stack.pop_n t.stack int_length - |> List.map (function - | Value.String s -> s - | _ -> assert false) - in - let record = StringMap.of_list @@ List.combine keys values in - let value = Value.Record record in - Stack.push_value t.stack value; - call_next_instruction t + fun t -> + let values = Array.to_list @@ Stack.pop_n t.stack length in + let keys = + Stack.pop_n t.stack length + |> Array.to_list + |> List.map (function + | Value.String s -> s + | _ -> assert false) + in + let record = StringMap.of_list @@ List.combine keys values in + let value = Value.Record record in + Stack.push_value t.stack value; + call_next_instruction t ;; let execute_current_closure t = @@ -905,22 +898,16 @@ let execute_current_closure t = ;; let execute_closure fn_addr num_free_variables = - let num_free_variables = Int32.to_int num_free_variables in - fun t -> - let fn = - match Int32.Map.find fn_addr t.constants with - | Value.Function fn -> fn - | _ -> assert false - in - let free_variables = - num_free_variables - |> Stack.pop_n t.stack - |> List.mapi (fun index value -> (Int32.of_int index, value)) - |> Int32.Map.of_list - in - let closure = Value.Closure { fn; free_variables } in - Stack.push_value t.stack closure; - call_next_instruction t + fun t -> + let fn = + match Array.get t.constants fn_addr with + | Value.Function fn -> fn + | _ -> assert false + in + let free_variables = Stack.pop_n t.stack num_free_variables in + let closure = Value.Closure { fn; free_variables } in + Stack.push_value t.stack closure; + call_next_instruction t ;; let execute_return t = @@ -1010,7 +997,7 @@ let resolve_constant_functions ~function_count constants = Array.set resolved_functions closure.fn.fn_addr instructions | Value.BuiltinFunction _ -> () in - Int32.Map.iter (fun _ -> resolve_from_value) constants; + Array.iter resolve_from_value constants; resolved_functions ;; @@ -1020,7 +1007,7 @@ let eval bytecode = let instructions = Array.append (resolve_instructions code.instructions) [| execute_halt |] in - let constants = code.constants in + let constants = Dynarray.to_array @@ code.constants in let resolved_functions = resolve_constant_functions ~function_count:!function_count constants in diff --git a/lib/pinc_vm/vm_stack.ml b/lib/pinc_vm/vm_stack.ml index 1ed038f..3f0b018 100644 --- a/lib/pinc_vm/vm_stack.ml +++ b/lib/pinc_vm/vm_stack.ml @@ -239,7 +239,7 @@ let[@inline] drop t = t.stack_pointer <- t.stack_pointer - 1 let[@inline] pop_n t n = t.stack_pointer <- t.stack_pointer - n; - List.init n (fun index -> get t (t.stack_pointer + index)) + Array.init n (fun index -> get t (t.stack_pointer + index)) ;; let[@inline] last_popped_element t = get t t.stack_pointer