From 19537a26b6baef15bc509fce8987cf9471b412a4 Mon Sep 17 00:00:00 2001 From: Dave Lucia Date: Wed, 11 Feb 2026 04:33:07 -0800 Subject: [PATCH 1/2] feat: integrate styler --- .formatter.exs | 3 +- lib/lua.ex | 47 ++++++----- lib/lua/api.ex | 13 ++- lib/lua/ast/block.ex | 6 +- lib/lua/ast/builder.ex | 8 +- lib/lua/ast/expr.ex | 25 +++--- lib/lua/ast/pretty_printer.ex | 67 +++++---------- lib/lua/ast/statement.ex | 4 +- lib/lua/ast/walker.ex | 15 ++-- lib/lua/compiler.ex | 19 ++--- lib/lua/compiler/codegen.ex | 49 ++++------- lib/lua/compiler/instruction.ex | 9 +- lib/lua/compiler/scope.ex | 33 ++------ lib/lua/compiler_exception.ex | 5 +- lib/lua/lexer.ex | 53 +++++------- lib/lua/parser.ex | 81 +++++++++--------- lib/lua/parser/error.ex | 12 ++- lib/lua/parser/recovery.ex | 10 +-- lib/lua/runtime_exception.ex | 5 +- lib/lua/util.ex | 9 +- lib/lua/vm.ex | 3 +- lib/lua/vm/argument_error.ex | 8 +- lib/lua/vm/error_formatter.ex | 18 ++-- lib/lua/vm/executor.ex | 111 +++++-------------------- lib/lua/vm/state.ex | 3 +- lib/lua/vm/stdlib.ex | 108 ++++++++++++------------ lib/lua/vm/stdlib/string.ex | 17 ++-- lib/lua/vm/stdlib/table.ex | 26 +++--- lib/lua/vm/value.ex | 37 ++++----- lib/mix/tasks/lua.get_tests.ex | 8 +- mix.exs | 3 +- mix.lock | 1 + test/lua/api_test.exs | 2 - test/lua/ast/builder_test.exs | 6 +- test/lua/ast/meta_test.exs | 2 +- test/lua/ast/pretty_printer_test.exs | 50 ++++++----- test/lua/ast/walker_test.exs | 14 ++-- test/lua/compiler/integration_test.exs | 50 +++++------ test/lua/compiler/source_line_test.exs | 6 +- test/lua/error_messages_test.exs | 23 ++--- test/lua/lexer_test.exs | 8 +- test/lua/parser/comment_test.exs | 8 +- test/lua/parser/error_test.exs | 1 + test/lua/parser/error_unit_test.exs | 6 +- test/lua/parser/expr_test.exs | 4 +- test/lua/parser/pratt_test.exs | 1 + test/lua/parser/precedence_test.exs | 3 +- test/lua/parser/recovery_test.exs | 2 +- test/lua/parser/statement_test.exs | 4 +- test/lua/runtime_exception_test.exs | 6 +- test/lua/vm/arithmetic_test.exs | 43 +++++----- test/lua/vm/call_stack_test.exs | 4 +- test/lua/vm/metatable_test.exs | 66 ++++++++------- test/lua/vm/pcall_test.exs | 15 ++-- test/lua/vm/stdlib/math_test.exs | 39 +++++---- test/lua/vm/stdlib/table_test.exs | 29 ++++--- test/lua/vm/stdlib/util_test.exs | 2 +- test/lua/vm/string_test.exs | 102 ++++++++++++----------- test/lua/vm/value_test.exs | 3 +- test/lua53_suite_test.exs | 1 + test/lua_test.exs | 14 +++- test/support/lua_test_case.ex | 15 ++-- 62 files changed, 622 insertions(+), 723 deletions(-) diff --git a/.formatter.exs b/.formatter.exs index d2cda26..935d310 100644 --- a/.formatter.exs +++ b/.formatter.exs @@ -1,4 +1,5 @@ # Used by "mix format" [ - inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"], + plugins: [Styler] ] diff --git a/lib/lua.ex b/lib/lua.ex index d913b4c..8084045 100644 --- a/lib/lua.ex +++ b/lib/lua.ex @@ -1,10 +1,19 @@ +external_resource = "README.md" + defmodule Lua do - @external_resource "README.md" - @moduledoc @external_resource + @moduledoc external_resource |> File.read!() |> String.split("") |> Enum.fetch!(1) + alias Lua.Util + alias Lua.VM.AssertionError + alias Lua.VM.RuntimeError + alias Lua.VM.State + alias Lua.VM.TypeError + alias Lua.VM.Value + + @external_resource external_resource @type t :: %__MODULE__{} # Compiler.compile/1 currently always succeeds but the spec allows {:error, _} @@ -13,9 +22,6 @@ defmodule Lua do defstruct [:state] - alias Lua.Util - alias Lua.VM.{State, Value} - @default_sandbox [ [:io], [:file], @@ -66,7 +72,7 @@ defmodule Lua do opts = Keyword.validate!(opts, sandboxed: @default_sandbox, exclude: []) exclude = Keyword.fetch!(opts, :exclude) - state = State.new() |> Lua.VM.Stdlib.install() + state = Lua.VM.Stdlib.install(State.new()) opts |> Keyword.fetch!(:sandboxed) @@ -123,7 +129,7 @@ defmodule Lua do def sandbox(lua, path) do set!(lua, path, fn args -> raise Lua.RuntimeException, - "#{Lua.Util.format_function(path, Enum.count(args))} is sandboxed" + "#{Util.format_function(path, Enum.count(args))} is sandboxed" end) end @@ -222,7 +228,7 @@ defmodule Lua do case func.(args, wrap(state)) do {:error, reason, %__MODULE__{}} -> - raise Lua.VM.RuntimeError, value: reason + raise RuntimeError, value: reason {value, %__MODULE__{} = lua} -> value = List.wrap(value) @@ -457,13 +463,13 @@ defmodule Lua do e in [Lua.RuntimeException, Lua.CompilerException] -> reraise e, __STACKTRACE__ - e in [Lua.VM.RuntimeError] -> + e in [RuntimeError] -> reraise Lua.RuntimeException, Exception.message(e), __STACKTRACE__ - e in [Lua.VM.TypeError] -> + e in [TypeError] -> reraise Lua.RuntimeException, Exception.message(e), __STACKTRACE__ - e in [Lua.VM.AssertionError] -> + e in [AssertionError] -> reraise Lua.RuntimeException, Exception.message(e), __STACKTRACE__ e -> @@ -487,13 +493,13 @@ defmodule Lua do e in [Lua.RuntimeException, Lua.CompilerException] -> reraise e, __STACKTRACE__ - e in [Lua.VM.RuntimeError] -> + e in [RuntimeError] -> reraise Lua.RuntimeException, Exception.message(e), __STACKTRACE__ - e in [Lua.VM.TypeError] -> + e in [TypeError] -> reraise Lua.RuntimeException, Exception.message(e), __STACKTRACE__ - e in [Lua.VM.AssertionError] -> + e in [AssertionError] -> reraise Lua.RuntimeException, Exception.message(e), __STACKTRACE__ e -> @@ -586,8 +592,7 @@ defmodule Lua do 42 """ - def call_function(%__MODULE__{state: state} = lua, func, args) - when is_tuple(func) do + def call_function(%__MODULE__{state: state} = lua, func, args) when is_tuple(func) do case do_call_function(func, args, state) do {:ok, results, new_state} -> {:ok, results, %{lua | state: new_state}} {:error, reason, new_state} -> {:error, reason, %{lua | state: new_state}} @@ -785,8 +790,7 @@ defmodule Lua do lua = ensure_scope!(lua, scope) lua = - module.__lua_functions__() - |> Enum.reduce(lua, fn {name, with_state?, variadic?}, lua -> + Enum.reduce(module.__lua_functions__(), lua, fn {name, with_state?, variadic?}, lua -> arities = Map.get(funcs, name) func = @@ -911,10 +915,10 @@ defmodule Lua do message: "maps must be explicitly encoded to tables using Lua.encode!/2" {:error, reason} -> - raise Lua.VM.RuntimeError, value: reason + raise RuntimeError, value: reason {:error, reason, %Lua{}} -> - raise Lua.VM.RuntimeError, value: reason + raise RuntimeError, value: reason {data, %Lua{} = returned_lua} -> data = List.wrap(data) @@ -942,8 +946,7 @@ defmodule Lua do end catch thrown_value -> - {:error, - "Value thrown during function '#{function_name}' execution: #{inspect(thrown_value)}"} + {:error, "Value thrown during function '#{function_name}' execution: #{inspect(thrown_value)}"} end defp ensure_scope!(lua, []) do diff --git a/lib/lua/api.ex b/lib/lua/api.ex index fa9c2cc..7b4427f 100644 --- a/lib/lua/api.ex +++ b/lib/lua/api.ex @@ -92,8 +92,6 @@ defmodule Lua.API do quote do @behaviour Lua.API - Module.register_attribute(__MODULE__, :lua_function, accumulate: true) - @before_compile Lua.API import Lua.API, only: [ @@ -108,6 +106,9 @@ defmodule Lua.API do is_mfa: 1 ] + Module.register_attribute(__MODULE__, :lua_function, accumulate: true) + @before_compile Lua.API + @impl Lua.API def scope do unquote(scope) @@ -161,7 +162,7 @@ defmodule Lua.API do """ defmacro runtime_exception!(message) do quote do - unless function_exported?(__MODULE__, :scope, 0) do + if !function_exported?(__MODULE__, :scope, 0) do raise "runtime_exception!/1 can only be called on modules implementing Lua.API" end @@ -248,8 +249,7 @@ defmodule Lua.API do quote do @lua_function validate_func!( - {unquote(name), true, - Module.delete_attribute(__MODULE__, :variadic) || false}, + {unquote(name), true, Module.delete_attribute(__MODULE__, :variadic) || false}, __MODULE__, @lua_function ) @@ -265,8 +265,7 @@ defmodule Lua.API do quote do @lua_function validate_func!( - {unquote(name), false, - Module.delete_attribute(__MODULE__, :variadic) || false}, + {unquote(name), false, Module.delete_attribute(__MODULE__, :variadic) || false}, __MODULE__, @lua_function ) diff --git a/lib/lua/ast/block.ex b/lib/lua/ast/block.ex index 6a0fc25..e74c9d8 100644 --- a/lib/lua/ast/block.ex +++ b/lib/lua/ast/block.ex @@ -6,7 +6,8 @@ defmodule Lua.AST.Block do Blocks create a new scope for local variables. """ - alias Lua.AST.{Meta, Statement} + alias Lua.AST.Meta + alias Lua.AST.Statement @type t :: %__MODULE__{ stmts: [Statement.t()], @@ -39,7 +40,8 @@ defmodule Lua.AST.Chunk do A chunk is essentially a block that represents a complete unit of Lua code. """ - alias Lua.AST.{Meta, Block} + alias Lua.AST.Block + alias Lua.AST.Meta @type t :: %__MODULE__{ block: Block.t(), diff --git a/lib/lua/ast/builder.ex b/lib/lua/ast/builder.ex index 221fccb..caa3fca 100644 --- a/lib/lua/ast/builder.ex +++ b/lib/lua/ast/builder.ex @@ -25,7 +25,11 @@ defmodule Lua.AST.Builder do ]) """ - alias Lua.AST.{Chunk, Block, Meta, Expr, Statement} + alias Lua.AST.Block + alias Lua.AST.Chunk + alias Lua.AST.Expr + alias Lua.AST.Meta + alias Lua.AST.Statement # Chunk and Block @@ -425,7 +429,7 @@ defmodule Lua.AST.Builder do %Statement.If{ condition: condition, then_block: block(then_stmts), - elseifs: Keyword.get(opts, :elseif, []) |> Enum.map(fn {c, s} -> {c, block(s)} end), + elseifs: opts |> Keyword.get(:elseif, []) |> Enum.map(fn {c, s} -> {c, block(s)} end), else_block: if(else_stmts = Keyword.get(opts, :else), do: block(else_stmts)), meta: Keyword.get(opts, :meta) } diff --git a/lib/lua/ast/expr.ex b/lib/lua/ast/expr.ex index 437511a..8a3d0b5 100644 --- a/lib/lua/ast/expr.ex +++ b/lib/lua/ast/expr.ex @@ -5,6 +5,7 @@ defmodule Lua.AST.Expr do All expression nodes include a `meta` field for position tracking. """ + alias Lua.AST.Expr alias Lua.AST.Meta defmodule Nil do @@ -74,8 +75,8 @@ defmodule Lua.AST.Expr do @type t :: %__MODULE__{ op: op(), - left: Lua.AST.Expr.t(), - right: Lua.AST.Expr.t(), + left: Expr.t(), + right: Expr.t(), meta: Meta.t() | nil } end @@ -95,7 +96,7 @@ defmodule Lua.AST.Expr do @type t :: %__MODULE__{ op: op(), - operand: Lua.AST.Expr.t(), + operand: Expr.t(), meta: Meta.t() | nil } end @@ -112,8 +113,8 @@ defmodule Lua.AST.Expr do defstruct [:fields, :meta] @type field :: - {:list, Lua.AST.Expr.t()} - | {:record, Lua.AST.Expr.t(), Lua.AST.Expr.t()} + {:list, Expr.t()} + | {:record, Expr.t(), Expr.t()} @type t :: %__MODULE__{ fields: [field()], @@ -128,8 +129,8 @@ defmodule Lua.AST.Expr do defstruct [:func, :args, :meta] @type t :: %__MODULE__{ - func: Lua.AST.Expr.t(), - args: [Lua.AST.Expr.t()], + func: Expr.t(), + args: [Expr.t()], meta: Meta.t() | nil } end @@ -143,9 +144,9 @@ defmodule Lua.AST.Expr do defstruct [:object, :method, :args, :meta] @type t :: %__MODULE__{ - object: Lua.AST.Expr.t(), + object: Expr.t(), method: String.t(), - args: [Lua.AST.Expr.t()], + args: [Expr.t()], meta: Meta.t() | nil } end @@ -157,8 +158,8 @@ defmodule Lua.AST.Expr do defstruct [:table, :key, :meta] @type t :: %__MODULE__{ - table: Lua.AST.Expr.t(), - key: Lua.AST.Expr.t(), + table: Expr.t(), + key: Expr.t(), meta: Meta.t() | nil } end @@ -172,7 +173,7 @@ defmodule Lua.AST.Expr do defstruct [:table, :field, :meta] @type t :: %__MODULE__{ - table: Lua.AST.Expr.t(), + table: Expr.t(), field: String.t(), meta: Meta.t() | nil } diff --git a/lib/lua/ast/pretty_printer.ex b/lib/lua/ast/pretty_printer.ex index c4c2128..4aec0e2 100644 --- a/lib/lua/ast/pretty_printer.ex +++ b/lib/lua/ast/pretty_printer.ex @@ -18,7 +18,10 @@ defmodule Lua.AST.PrettyPrinter do PrettyPrinter.print(ast, indent: 4) """ - alias Lua.AST.{Chunk, Block, Expr, Statement} + alias Lua.AST.Block + alias Lua.AST.Chunk + alias Lua.AST.Expr + alias Lua.AST.Statement @type ast_node :: Chunk.t() @@ -56,8 +59,7 @@ defmodule Lua.AST.PrettyPrinter do # Block defp do_print(%Block{stmts: stmts}, level, indent_size) do stmts - |> Enum.map(&do_print(&1, level, indent_size)) - |> Enum.join("\n") + |> Enum.map_join("\n", &do_print(&1, level, indent_size)) |> Kernel.<>("\n") end @@ -129,14 +131,14 @@ defmodule Lua.AST.PrettyPrinter do defp do_print(%Expr.Call{func: func, args: args}, level, indent_size) do func_str = do_print(func, level, indent_size) - args_str = Enum.map(args, &do_print(&1, level, indent_size)) |> Enum.join(", ") + args_str = Enum.map_join(args, ", ", &do_print(&1, level, indent_size)) "#{func_str}(#{args_str})" end defp do_print(%Expr.MethodCall{object: obj, method: method, args: args}, level, indent_size) do obj_str = do_print(obj, level, indent_size) - args_str = Enum.map(args, &do_print(&1, level, indent_size)) |> Enum.join(", ") + args_str = Enum.map_join(args, ", ", &do_print(&1, level, indent_size)) "#{obj_str}:#{method}(#{args_str})" end @@ -155,12 +157,10 @@ defmodule Lua.AST.PrettyPrinter do defp do_print(%Expr.Function{params: params, body: body}, level, indent_size) do params_str = - params - |> Enum.map(fn + Enum.map_join(params, ", ", fn :vararg -> "..." name -> name end) - |> Enum.join(", ") body_str = print_block_body(body, level + 1, indent_size) @@ -170,8 +170,8 @@ defmodule Lua.AST.PrettyPrinter do # Statements defp do_print(%Statement.Assign{targets: targets, values: values} = stmt, level, indent_size) do - targets_str = Enum.map(targets, &do_print(&1, level, indent_size)) |> Enum.join(", ") - values_str = Enum.map(values, &do_print(&1, level, indent_size)) |> Enum.join(", ") + targets_str = Enum.map_join(targets, ", ", &do_print(&1, level, indent_size)) + values_str = Enum.map_join(values, ", ", &do_print(&1, level, indent_size)) stmt_line = "#{indent(level, indent_size)}#{targets_str} = #{values_str}" print_with_comments(stmt, level, indent_size, fn -> stmt_line end) @@ -182,7 +182,7 @@ defmodule Lua.AST.PrettyPrinter do stmt_line = if values && values != [] do - values_str = Enum.map(values, &do_print(&1, level, indent_size)) |> Enum.join(", ") + values_str = Enum.map_join(values, ", ", &do_print(&1, level, indent_size)) "#{indent(level, indent_size)}local #{names_str} = #{values_str}" else "#{indent(level, indent_size)}local #{names_str}" @@ -191,18 +191,12 @@ defmodule Lua.AST.PrettyPrinter do print_with_comments(stmt, level, indent_size, fn -> stmt_line end) end - defp do_print( - %Statement.LocalFunc{name: name, params: params, body: body} = stmt, - level, - indent_size - ) do + defp do_print(%Statement.LocalFunc{name: name, params: params, body: body} = stmt, level, indent_size) do params_str = - params - |> Enum.map(fn + Enum.map_join(params, ", ", fn :vararg -> "..." name -> name end) - |> Enum.join(", ") body_str = print_block_body(body, level + 1, indent_size) @@ -212,18 +206,12 @@ defmodule Lua.AST.PrettyPrinter do print_with_comments(stmt, level, indent_size, fn -> stmt_line end) end - defp do_print( - %Statement.FuncDecl{name: name, params: params, body: body} = stmt, - level, - indent_size - ) do + defp do_print(%Statement.FuncDecl{name: name, params: params, body: body} = stmt, level, indent_size) do params_str = - params - |> Enum.map(fn + Enum.map_join(params, ", ", fn :vararg -> "..." param_name -> param_name end) - |> Enum.join(", ") body_str = print_block_body(body, level + 1, indent_size) @@ -239,12 +227,7 @@ defmodule Lua.AST.PrettyPrinter do end defp do_print( - %Statement.If{ - condition: cond, - then_block: then_block, - elseifs: elseifs, - else_block: else_block - } = stmt, + %Statement.If{condition: cond, then_block: then_block, elseifs: elseifs, else_block: else_block} = stmt, level, indent_size ) do @@ -262,8 +245,6 @@ defmodule Lua.AST.PrettyPrinter do if else_block do b_str = print_block_body(else_block, level + 1, indent_size) "#{indent(level, indent_size)}else\n#{b_str}" - else - nil end parts = ["#{indent(level, indent_size)}if #{cond_str} then\n#{then_str}"] ++ elseif_strs @@ -321,13 +302,9 @@ defmodule Lua.AST.PrettyPrinter do print_with_comments(stmt, level, indent_size, fn -> stmt_line end) end - defp do_print( - %Statement.ForIn{vars: vars, iterators: iterators, body: body} = stmt, - level, - indent_size - ) do + defp do_print(%Statement.ForIn{vars: vars, iterators: iterators, body: body} = stmt, level, indent_size) do vars_str = Enum.join(vars, ", ") - iterators_str = Enum.map(iterators, &do_print(&1, level, indent_size)) |> Enum.join(", ") + iterators_str = Enum.map_join(iterators, ", ", &do_print(&1, level, indent_size)) body_str = print_block_body(body, level + 1, indent_size) stmt_line = @@ -348,7 +325,7 @@ defmodule Lua.AST.PrettyPrinter do if values == [] do "#{indent(level, indent_size)}return" else - values_str = Enum.map(values, &do_print(&1, level, indent_size)) |> Enum.join(", ") + values_str = Enum.map_join(values, ", ", &do_print(&1, level, indent_size)) "#{indent(level, indent_size)}return #{values_str}" end @@ -378,8 +355,7 @@ defmodule Lua.AST.PrettyPrinter do defp print_block_body(%Block{stmts: stmts}, level, indent_size) do stmts - |> Enum.map(&do_print(&1, level, indent_size)) - |> Enum.join("\n") + |> Enum.map_join("\n", &do_print(&1, level, indent_size)) |> Kernel.<>("\n") end @@ -563,8 +539,7 @@ defmodule Lua.AST.PrettyPrinter do "" else comments - |> Enum.map(&format_comment(&1, level, indent_size)) - |> Enum.join("\n") + |> Enum.map_join("\n", &format_comment(&1, level, indent_size)) |> Kernel.<>("\n") end end diff --git a/lib/lua/ast/statement.ex b/lib/lua/ast/statement.ex index 567c463..8fcf6b6 100644 --- a/lib/lua/ast/statement.ex +++ b/lib/lua/ast/statement.ex @@ -5,7 +5,9 @@ defmodule Lua.AST.Statement do All statement nodes include a `meta` field for position tracking. """ - alias Lua.AST.{Meta, Expr, Block} + alias Lua.AST.Block + alias Lua.AST.Expr + alias Lua.AST.Meta defmodule Assign do @moduledoc """ diff --git a/lib/lua/ast/walker.ex b/lib/lua/ast/walker.ex index 161ea74..3ad2e11 100644 --- a/lib/lua/ast/walker.ex +++ b/lib/lua/ast/walker.ex @@ -27,7 +27,10 @@ defmodule Lua.AST.Walker do Walker.walk(ast, fn node -> ... end, order: :post) """ - alias Lua.AST.{Chunk, Block, Expr, Statement} + alias Lua.AST.Block + alias Lua.AST.Chunk + alias Lua.AST.Expr + alias Lua.AST.Statement @type ast_node :: Chunk.t() @@ -119,7 +122,8 @@ defmodule Lua.AST.Walker do end defp walk_children(node, visitor, order) do - children(node) + node + |> children() |> Enum.each(fn child -> do_walk(child, visitor, order) end) end @@ -198,7 +202,7 @@ defmodule Lua.AST.Walker do mapped_elseifs = Enum.map(elseifs, fn {c, b} -> {do_map(c, mapper), do_map(b, mapper)} end) - mapped_else = if else_block, do: do_map(else_block, mapper), else: nil + mapped_else = if else_block, do: do_map(else_block, mapper) %{ stmt @@ -215,7 +219,7 @@ defmodule Lua.AST.Walker do %{stmt | body: do_map(body, mapper), condition: do_map(cond, mapper)} %Statement.ForNum{var: _var, start: start, limit: limit, step: step, body: body} = stmt -> - mapped_step = if step, do: do_map(step, mapper), else: nil + mapped_step = if step, do: do_map(step, mapper) %{ stmt @@ -250,7 +254,8 @@ defmodule Lua.AST.Walker do defp do_reduce(node, acc, reducer) do acc = reducer.(node, acc) - children(node) + node + |> children() |> Enum.reduce(acc, fn child, acc -> do_reduce(child, acc, reducer) end) end diff --git a/lib/lua/compiler.ex b/lib/lua/compiler.ex index afbc5ff..0434d87 100644 --- a/lib/lua/compiler.ex +++ b/lib/lua/compiler.ex @@ -6,7 +6,9 @@ defmodule Lua.Compiler do """ alias Lua.AST.Chunk - alias Lua.Compiler.{Scope, Codegen, Prototype} + alias Lua.Compiler.Codegen + alias Lua.Compiler.Prototype + alias Lua.Compiler.Scope @type compile_opts :: [ source: binary() @@ -17,9 +19,8 @@ defmodule Lua.Compiler do """ @spec compile(Chunk.t(), compile_opts()) :: {:ok, Prototype.t()} | {:error, term()} def compile(%Chunk{} = chunk, opts \\ []) do - with {:ok, scope_state} <- Scope.resolve(chunk, opts), - {:ok, prototype} <- Codegen.generate(chunk, scope_state, opts) do - {:ok, prototype} + with {:ok, scope_state} <- Scope.resolve(chunk, opts) do + Codegen.generate(chunk, scope_state, opts) end end @@ -28,11 +29,9 @@ defmodule Lua.Compiler do """ @spec compile!(Chunk.t(), compile_opts()) :: Prototype.t() def compile!(%Chunk{} = chunk, opts \\ []) do - case compile(chunk, opts) do - {:ok, prototype} -> - prototype - # TODO bring back when the compiler can return errors - # {:error, reason} -> raise "Compilation failed: #{inspect(reason)}" - end + {:ok, prototype} = compile(chunk, opts) + prototype + # TODO bring back when the compiler can return errors + # {:error, reason} -> raise "Compilation failed: #{inspect(reason)}" end end diff --git a/lib/lua/compiler/codegen.ex b/lib/lua/compiler/codegen.ex index d2ca3fb..a61b405 100644 --- a/lib/lua/compiler/codegen.ex +++ b/lib/lua/compiler/codegen.ex @@ -3,8 +3,13 @@ defmodule Lua.Compiler.Codegen do Code generation - transforms AST into instructions. """ - alias Lua.AST.{Chunk, Block, Statement, Expr} - alias Lua.Compiler.{Prototype, Instruction, Scope} + alias Lua.AST.Block + alias Lua.AST.Chunk + alias Lua.AST.Expr + alias Lua.AST.Statement + alias Lua.Compiler.Instruction + alias Lua.Compiler.Prototype + alias Lua.Compiler.Scope @doc """ Generates instructions from a scope-resolved AST. @@ -57,8 +62,7 @@ defmodule Lua.Compiler.Codegen do defp compute_line_range(%Block{stmts: stmts}) do lines = - stmts - |> Enum.flat_map(fn + Enum.flat_map(stmts, fn %{meta: %{start: %{line: start_line}, stop: %{line: stop_line}}} -> [start_line, stop_line] @@ -226,12 +230,7 @@ defmodule Lua.Compiler.Codegen do end defp gen_statement( - %Statement.If{ - condition: condition, - then_block: then_block, - elseifs: elseifs, - else_block: else_block - }, + %Statement.If{condition: condition, then_block: then_block, elseifs: elseifs, else_block: else_block}, ctx ) do # Generate code for the condition @@ -276,16 +275,7 @@ defmodule Lua.Compiler.Codegen do {[loop_instruction], ctx} end - defp gen_statement( - %Statement.ForNum{ - var: var, - start: start_expr, - limit: limit_expr, - step: step_expr, - body: body - }, - ctx - ) do + defp gen_statement(%Statement.ForNum{var: var, start: start_expr, limit: limit_expr, step: step_expr, body: body}, ctx) do # Get the loop variable's register from scope loop_var_reg = ctx.scope.locals[var] @@ -331,10 +321,7 @@ defmodule Lua.Compiler.Codegen do [loop_instruction], ctx} end - defp gen_statement( - %Statement.ForIn{vars: vars, iterators: iterators, body: body}, - ctx - ) do + defp gen_statement(%Statement.ForIn{vars: vars, iterators: iterators, body: body}, ctx) do # Look up loop variable registers from scope var_regs = Enum.map(vars, fn name -> ctx.scope.locals[name] end) @@ -442,10 +429,7 @@ defmodule Lua.Compiler.Codegen do {get_instructions, table_reg, ctx} = gen_expr(%Expr.Var{name: first}, ctx) {final_instructions, final_table_reg, ctx} = - Enum.reduce(Enum.slice(rest, 0..-2//1), {get_instructions, table_reg, ctx}, fn field, - {instrs, - reg, - ctx} -> + Enum.reduce(Enum.slice(rest, 0..-2//1), {get_instructions, table_reg, ctx}, fn field, {instrs, reg, ctx} -> field_reg = ctx.next_reg ctx = %{ctx | next_reg: field_reg + 1} {instrs ++ [Instruction.get_field(field_reg, reg, field)], field_reg, ctx} @@ -453,8 +437,7 @@ defmodule Lua.Compiler.Codegen do last_field = List.last(rest) - {final_instructions ++ [Instruction.set_field(final_table_reg, last_field, closure_reg)], - ctx} + {final_instructions ++ [Instruction.set_field(final_table_reg, last_field, closure_reg)], ctx} end end @@ -906,8 +889,7 @@ defmodule Lua.Compiler.Codegen do case key_expr do %Expr.String{value: name} -> - {instructions ++ value_instructions ++ [Instruction.set_field(dest, name, val_reg)], - ctx} + {instructions ++ value_instructions ++ [Instruction.set_field(dest, name, val_reg)], ctx} _ -> {key_instructions, key_reg, ctx} = gen_expr(key_expr, ctx) @@ -935,8 +917,7 @@ defmodule Lua.Compiler.Codegen do dest = ctx.next_reg ctx = %{ctx | next_reg: dest + 1} - {table_instructions ++ key_instructions ++ [Instruction.get_table(dest, table_reg, key_reg)], - dest, ctx} + {table_instructions ++ key_instructions ++ [Instruction.get_table(dest, table_reg, key_reg)], dest, ctx} end defp gen_expr(%Expr.MethodCall{object: obj_expr, method: method, args: args}, ctx) do diff --git a/lib/lua/compiler/instruction.ex b/lib/lua/compiler/instruction.ex index d16278c..c2bbe35 100644 --- a/lib/lua/compiler/instruction.ex +++ b/lib/lua/compiler/instruction.ex @@ -21,8 +21,7 @@ defmodule Lua.Compiler.Instruction do def set_global(name, source), do: {:set_global, name, source} # Table operations - def new_table(dest, array_hint \\ 0, hash_hint \\ 0), - do: {:new_table, dest, array_hint, hash_hint} + def new_table(dest, array_hint \\ 0, hash_hint \\ 0), do: {:new_table, dest, array_hint, hash_hint} def get_table(dest, table, key), do: {:get_table, dest, table, key} def set_table(table, key, value), do: {:set_table, table, key, value} @@ -64,11 +63,9 @@ defmodule Lua.Compiler.Instruction do def test_and(dest, source, rest_body), do: {:test_and, dest, source, rest_body} def test_or(dest, source, rest_body), do: {:test_or, dest, source, rest_body} - def while_loop(condition_body, test_reg, loop_body), - do: {:while_loop, condition_body, test_reg, loop_body} + def while_loop(condition_body, test_reg, loop_body), do: {:while_loop, condition_body, test_reg, loop_body} - def repeat_loop(loop_body, condition_body, test_reg), - do: {:repeat_loop, loop_body, condition_body, test_reg} + def repeat_loop(loop_body, condition_body, test_reg), do: {:repeat_loop, loop_body, condition_body, test_reg} def numeric_for(base, loop_var, body), do: {:numeric_for, base, loop_var, body} def generic_for(base, var_count, body), do: {:generic_for, base, var_count, body} diff --git a/lib/lua/compiler/scope.ex b/lib/lua/compiler/scope.ex index fe3d71d..0b7c8b4 100644 --- a/lib/lua/compiler/scope.ex +++ b/lib/lua/compiler/scope.ex @@ -5,7 +5,10 @@ defmodule Lua.Compiler.Scope do Assigns registers to local variables and identifies upvalues and globals. """ - alias Lua.AST.{Chunk, Block, Statement, Expr} + alias Lua.AST.Block + alias Lua.AST.Chunk + alias Lua.AST.Expr + alias Lua.AST.Statement @type var_ref :: {:register, index :: non_neg_integer()} @@ -125,12 +128,7 @@ defmodule Lua.Compiler.Scope do end defp resolve_statement( - %Statement.If{ - condition: condition, - then_block: then_block, - elseifs: elseifs, - else_block: else_block - }, + %Statement.If{condition: condition, then_block: then_block, elseifs: elseifs, else_block: else_block}, state ) do # Resolve the main condition @@ -169,13 +167,7 @@ defmodule Lua.Compiler.Scope do end defp resolve_statement( - %Statement.ForNum{ - var: var, - start: start_expr, - limit: limit_expr, - step: step_expr, - body: body - }, + %Statement.ForNum{var: var, start: start_expr, limit: limit_expr, step: step_expr, body: body}, state ) do # Resolve start, limit, and step expressions with current scope @@ -202,10 +194,7 @@ defmodule Lua.Compiler.Scope do state end - defp resolve_statement( - %Statement.FuncDecl{params: params, body: body, is_method: is_method} = decl, - state - ) do + defp resolve_statement(%Statement.FuncDecl{params: params, body: body, is_method: is_method} = decl, state) do all_params = if is_method, do: ["self" | params], else: params resolve_function_scope(decl, all_params, body, state) end @@ -214,10 +203,7 @@ defmodule Lua.Compiler.Scope do resolve_expr(call, state) end - defp resolve_statement( - %Statement.ForIn{vars: vars, iterators: iterators, body: body}, - state - ) do + defp resolve_statement(%Statement.ForIn{vars: vars, iterators: iterators, body: body}, state) do # Resolve iterator expressions with current scope state = Enum.reduce(iterators, state, &resolve_expr/2) @@ -479,8 +465,7 @@ defmodule Lua.Compiler.Scope do newly_captured = func_scope_final.upvalue_descriptors |> Enum.filter(fn {type, _, _} -> type == :parent_local end) - |> Enum.map(fn {:parent_local, _reg, name} -> name end) - |> MapSet.new() + |> MapSet.new(fn {:parent_local, _reg, name} -> name end) # Restore previous scope, merging newly captured locals %{ diff --git a/lib/lua/compiler_exception.ex b/lib/lua/compiler_exception.ex index c01e323..8fcc164 100644 --- a/lib/lua/compiler_exception.ex +++ b/lib/lua/compiler_exception.ex @@ -1,8 +1,9 @@ defmodule Lua.CompilerException do - defexception [:errors, :state] - + @moduledoc false alias Lua.Util + defexception [:errors, :state] + def exception(formatted: errors) when is_list(errors) do %__MODULE__{errors: errors} end diff --git a/lib/lua/lexer.ex b/lib/lua/lexer.ex index e55f330..f5afa4b 100644 --- a/lib/lua/lexer.ex +++ b/lib/lua/lexer.ex @@ -187,8 +187,7 @@ defmodule Lua.Lexer do end # Single-character operators and delimiters - defp do_tokenize(<>, acc, pos) - when c in [?+, ?-, ?*, ?/, ?%, ?^, ?#, ?&, ?|, ?~] do + defp do_tokenize(<>, acc, pos) when c in [?+, ?-, ?*, ?/, ?%, ?^, ?#, ?&, ?|, ?~] do op = case c do ?+ -> :add @@ -219,8 +218,7 @@ defmodule Lua.Lexer do do_tokenize(rest, [token | acc], advance_column(pos, 1)) end - defp do_tokenize(<>, acc, pos) - when c in [?(, ?), ?{, ?}, ?], ?;, ?,, ?., ?:] do + defp do_tokenize(<>, acc, pos) when c in [?(, ?), ?{, ?}, ?], ?;, ?,, ?., ?:] do delim = case c do ?( -> :lparen @@ -239,8 +237,7 @@ defmodule Lua.Lexer do end # Identifiers and keywords - defp do_tokenize(<>, acc, pos) - when c in ?a..?z or c in ?A..?Z or c == ?_ do + defp do_tokenize(<>, acc, pos) when c in ?a..?z or c in ?A..?Z or c == ?_ do scan_identifier(<>, "", acc, pos, pos) end @@ -485,8 +482,7 @@ defmodule Lua.Lexer do end # Scan decimal number - defp scan_number(<>, num_acc, acc, pos, start_pos) - when c in ?0..?9 do + defp scan_number(<>, num_acc, acc, pos, start_pos) when c in ?0..?9 do scan_number(rest, num_acc <> <>, acc, advance_column(pos, 1), start_pos) end @@ -495,8 +491,7 @@ defmodule Lua.Lexer do finalize_number(num_acc, <<".">>, acc, pos, start_pos) end - defp scan_number(<<".", c, rest::binary>>, num_acc, acc, pos, start_pos) - when c in ?0..?9 do + defp scan_number(<<".", c, rest::binary>>, num_acc, acc, pos, start_pos) when c in ?0..?9 do # Decimal point with digit following scan_float(rest, num_acc <> "." <> <>, acc, advance_column(pos, 2), start_pos) end @@ -506,8 +501,7 @@ defmodule Lua.Lexer do finalize_number(num_acc, <<".", rest::binary>>, acc, pos, start_pos) end - defp scan_number(<>, num_acc, acc, pos, start_pos) - when c in [?e, ?E] do + defp scan_number(<>, num_acc, acc, pos, start_pos) when c in [?e, ?E] do # Scientific notation scan_exponent(<>, num_acc, acc, pos, start_pos) end @@ -517,13 +511,11 @@ defmodule Lua.Lexer do end # Scan float part (after decimal point) - defp scan_float(<>, num_acc, acc, pos, start_pos) - when c in ?0..?9 do + defp scan_float(<>, num_acc, acc, pos, start_pos) when c in ?0..?9 do scan_float(rest, num_acc <> <>, acc, advance_column(pos, 1), start_pos) end - defp scan_float(<>, num_acc, acc, pos, start_pos) - when c in [?e, ?E] do + defp scan_float(<>, num_acc, acc, pos, start_pos) when c in [?e, ?E] do scan_exponent(<>, num_acc, acc, pos, start_pos) end @@ -532,18 +524,15 @@ defmodule Lua.Lexer do end # Scan scientific notation exponent - defp scan_exponent(<>, num_acc, acc, pos, start_pos) - when c in [?e, ?E] and sign in [?+, ?-] do + defp scan_exponent(<>, num_acc, acc, pos, start_pos) when c in [?e, ?E] and sign in [?+, ?-] do scan_exponent_digits(rest, num_acc <> <>, acc, advance_column(pos, 2), start_pos) end - defp scan_exponent(<>, num_acc, acc, pos, start_pos) - when c in [?e, ?E] do + defp scan_exponent(<>, num_acc, acc, pos, start_pos) when c in [?e, ?E] do scan_exponent_digits(rest, num_acc <> <>, acc, advance_column(pos, 1), start_pos) end - defp scan_exponent_digits(<>, num_acc, acc, pos, start_pos) - when c in ?0..?9 do + defp scan_exponent_digits(<>, num_acc, acc, pos, start_pos) when c in ?0..?9 do scan_exponent_digits(rest, num_acc <> <>, acc, advance_column(pos, 1), start_pos) end @@ -582,17 +571,15 @@ defmodule Lua.Lexer do # Parse number string to integer or float defp parse_number(num_str) do - cond do - String.contains?(num_str, ".") or String.contains?(num_str, "e") or - String.contains?(num_str, "E") -> - case Float.parse(num_str) do - {num, ""} -> {:ok, num} - _ -> {:error, :invalid_number} - end - - true -> - {num, ""} = Integer.parse(num_str) - {:ok, num} + if String.contains?(num_str, ".") or String.contains?(num_str, "e") or + String.contains?(num_str, "E") do + case Float.parse(num_str) do + {num, ""} -> {:ok, num} + _ -> {:error, :invalid_number} + end + else + {num, ""} = Integer.parse(num_str) + {:ok, num} end end diff --git a/lib/lua/parser.ex b/lib/lua/parser.ex index 53016ef..1dc7145 100644 --- a/lib/lua/parser.ex +++ b/lib/lua/parser.ex @@ -5,15 +5,19 @@ defmodule Lua.Parser do Uses Pratt parsing for operator precedence in expressions. """ - alias Lua.AST.{Meta, Expr, Statement, Block, Chunk} - alias Lua.Parser.{Pratt, Comments} + alias Lua.AST.Block + alias Lua.AST.Chunk + alias Lua.AST.Expr + alias Lua.AST.Meta + alias Lua.AST.Statement alias Lua.Lexer + alias Lua.Parser.Comments + alias Lua.Parser.Error + alias Lua.Parser.Pratt @type token :: Lexer.token() @type parse_result(t) :: {:ok, t, [token()]} | {:error, term()} - alias Lua.Parser.Error - @doc """ Parses Lua source code into an AST. @@ -244,9 +248,7 @@ defmodule Lua.Parser do {:ok, _, rest6} <- expect(rest5, :delimiter, :rparen), {:ok, body, rest7} <- parse_block(rest6), {:ok, _, rest8} <- expect(rest7, :keyword, :end) do - {:ok, - %Statement.LocalFunc{name: name, params: params, body: body, meta: Meta.new(pos)}, - rest8} + {:ok, %Statement.LocalFunc{name: name, params: params, body: body, meta: Meta.new(pos)}, rest8} end {:error, reason} -> @@ -263,8 +265,7 @@ defmodule Lua.Parser do case parse_expr_list(rest3) do {:ok, values, rest4} -> - {:ok, %Statement.Local{names: names, values: values, meta: Meta.new(pos)}, - rest4} + {:ok, %Statement.Local{names: names, values: values, meta: Meta.new(pos)}, rest4} {:error, reason} -> {:error, reason} @@ -280,8 +281,7 @@ defmodule Lua.Parser do end _ -> - {:error, - {:unexpected_token, peek(rest), "Expected identifier or 'function' after 'local'"}} + {:error, {:unexpected_token, peek(rest), "Expected identifier or 'function' after 'local'"}} end end @@ -774,34 +774,32 @@ defmodule Lua.Parser do end {:operator, op, pos} -> - cond do - Pratt.is_binary_op?(op) -> - case Pratt.binding_power(op) do - {left_bp, right_bp} when left_bp >= min_prec -> - {_, rest} = consume(tokens) - binop = Pratt.token_to_binop(op) - - case parse_expr(rest, right_bp) do - {:ok, right, rest2} -> - new_left = %Expr.BinOp{ - op: binop, - left: left, - right: right, - meta: Meta.new(pos) - } - - parse_infix(new_left, rest2, min_prec) + if Pratt.is_binary_op?(op) do + case Pratt.binding_power(op) do + {left_bp, right_bp} when left_bp >= min_prec -> + {_, rest} = consume(tokens) + binop = Pratt.token_to_binop(op) - {:error, reason} -> - {:error, reason} - end + case parse_expr(rest, right_bp) do + {:ok, right, rest2} -> + new_left = %Expr.BinOp{ + op: binop, + left: left, + right: right, + meta: Meta.new(pos) + } - _ -> - {:ok, left, tokens} - end + parse_infix(new_left, rest2, min_prec) - true -> - {:ok, left, tokens} + {:error, reason} -> + {:error, reason} + end + + _ -> + {:ok, left, tokens} + end + else + {:ok, left, tokens} end # Postfix: function call @@ -1107,15 +1105,11 @@ defmodule Lua.Parser do {:ok, token, rest} {type, _, pos} when type != nil -> - {:error, - {:unexpected_token, type, pos, - "Expected #{inspect(expected_type)}, got #{inspect(type)}"}} + {:error, {:unexpected_token, type, pos, "Expected #{inspect(expected_type)}, got #{inspect(type)}"}} {type, pos} when is_map(pos) -> # Token without value (like :eof) - {:error, - {:unexpected_token, type, pos, - "Expected #{inspect(expected_type)}, got #{inspect(type)}"}} + {:error, {:unexpected_token, type, pos, "Expected #{inspect(expected_type)}, got #{inspect(type)}"}} nil -> {:error, {:unexpected_end, "Expected #{inspect(expected_type)}"}} @@ -1141,8 +1135,7 @@ defmodule Lua.Parser do "Expected #{inspect(expected_type)}:#{inspect(expected_value)}, got #{inspect(type)}"}} nil -> - {:error, - {:unexpected_end, "Expected #{inspect(expected_type)}:#{inspect(expected_value)}"}} + {:error, {:unexpected_end, "Expected #{inspect(expected_type)}:#{inspect(expected_value)}"}} end end diff --git a/lib/lua/parser/error.ex b/lib/lua/parser/error.ex index 73430b3..52b42ee 100644 --- a/lib/lua/parser/error.ex +++ b/lib/lua/parser/error.ex @@ -174,8 +174,7 @@ defmodule Lua.Parser.Error do [] end - (header ++ message_lines ++ context_lines ++ suggestion_lines ++ related_lines) - |> Enum.join("\n") + Enum.join(header ++ message_lines ++ context_lines ++ suggestion_lines ++ related_lines, "\n") end @doc """ @@ -202,8 +201,7 @@ defmodule Lua.Parser.Error do ] end) - (header ++ error_lines) - |> Enum.join("\n") + Enum.join(header ++ error_lines, "\n") end # Private helpers @@ -217,7 +215,8 @@ defmodule Lua.Parser.Error do end_line = min(length(lines), line_num + 2) context_lines = - Enum.slice(lines, (start_line - 1)..(end_line - 1)) + lines + |> Enum.slice((start_line - 1)..(end_line - 1)) |> Enum.with_index(start_line) |> Enum.flat_map(fn {line, num} -> line_str = format_line_number(num) <> " │ " <> line @@ -339,7 +338,6 @@ defmodule Lua.Parser.Error do text |> String.split("\n") - |> Enum.map(&(prefix <> &1)) - |> Enum.join("\n") + |> Enum.map_join("\n", &(prefix <> &1)) end end diff --git a/lib/lua/parser/recovery.ex b/lib/lua/parser/recovery.ex index 48a6970..5d17c87 100644 --- a/lib/lua/parser/recovery.ex +++ b/lib/lua/parser/recovery.ex @@ -6,9 +6,9 @@ defmodule Lua.Parser.Recovery do collecting multiple errors in a single parse pass. """ - alias Lua.Parser.Error - alias Lua.Lexer alias Lua.AST.Meta + alias Lua.Lexer + alias Lua.Parser.Error @type token :: Lexer.token() @type recovery_result :: {:recovered, [token()], [Error.t()]} | {:failed, [Error.t()]} @@ -153,8 +153,7 @@ defmodule Lua.Parser.Recovery do defp find_statement_boundary([]), do: :not_found - defp find_closing_delimiter([{:delimiter, delim, _} | rest], target, depth) - when delim == target do + defp find_closing_delimiter([{:delimiter, delim, _} | rest], target, depth) when delim == target do if depth == 1 do {:ok, rest} else @@ -175,8 +174,7 @@ defmodule Lua.Parser.Recovery do end end - defp find_closing_delimiter([{:keyword, kw, _} | rest], :end, depth) - when kw in [:if, :while, :for, :function, :do] do + defp find_closing_delimiter([{:keyword, kw, _} | rest], :end, depth) when kw in [:if, :while, :for, :function, :do] do find_closing_delimiter(rest, :end, depth + 1) end diff --git a/lib/lua/runtime_exception.ex b/lib/lua/runtime_exception.ex index f8be3a5..190b745 100644 --- a/lib/lua/runtime_exception.ex +++ b/lib/lua/runtime_exception.ex @@ -1,8 +1,9 @@ defmodule Lua.RuntimeException do - defexception [:message, :original, :state] - + @moduledoc false alias Lua.Util + defexception [:message, :original, :state] + @impl true def exception({:lua_error, error, _state}) do message = Util.format_error(error) diff --git a/lib/lua/util.ex b/lib/lua/util.ex index 641f905..3ef75d8 100644 --- a/lib/lua/util.ex +++ b/lib/lua/util.ex @@ -23,7 +23,7 @@ defmodule Lua.Util do def format_error(error) do case error do {:badarith, operator, values} -> - expression = values |> Enum.map(&to_string/1) |> Enum.join(" #{operator} ") + expression = Enum.map_join(values, " #{operator} ", &to_string/1) "bad arithmetic #{expression}" {:illegal_index, _type, message} -> @@ -59,10 +59,7 @@ defmodule Lua.Util do def format_stacktrace([], _, _), do: "" def format_stacktrace(stack, _, _) when is_list(stack) do - frames = - stack - |> Enum.map(&format_stack_frame/1) - |> Enum.join("\n") + frames = Enum.map_join(stack, "\n", &format_stack_frame/1) "stack traceback:\n" <> frames end @@ -119,7 +116,7 @@ defmodule Lua.Util do end defp format_args(arity) when is_integer(arity) do - underscores = List.duplicate("_", arity) |> Enum.join(", ") + underscores = "_" |> List.duplicate(arity) |> Enum.join(", ") "(" <> underscores <> ")" end diff --git a/lib/lua/vm.ex b/lib/lua/vm.ex index 0337958..6b22c1b 100644 --- a/lib/lua/vm.ex +++ b/lib/lua/vm.ex @@ -6,7 +6,8 @@ defmodule Lua.VM do """ alias Lua.Compiler.Prototype - alias Lua.VM.{State, Executor} + alias Lua.VM.Executor + alias Lua.VM.State @doc """ Executes a compiled prototype. diff --git a/lib/lua/vm/argument_error.ex b/lib/lua/vm/argument_error.ex index 7f2863c..9e458c8 100644 --- a/lib/lua/vm/argument_error.ex +++ b/lib/lua/vm/argument_error.ex @@ -56,13 +56,7 @@ defmodule Lua.VM.ArgumentError do end @impl true - def message(%__MODULE__{ - function_name: function_name, - arg_num: arg_num, - expected: expected, - got: got, - details: details - }) do + def message(%__MODULE__{function_name: function_name, arg_num: arg_num, expected: expected, got: got, details: details}) do build_message(function_name, arg_num, expected, got, details) end diff --git a/lib/lua/vm/error_formatter.ex b/lib/lua/vm/error_formatter.ex index f4771dd..00cf867 100644 --- a/lib/lua/vm/error_formatter.ex +++ b/lib/lua/vm/error_formatter.ex @@ -78,7 +78,8 @@ defmodule Lua.VM.ErrorFormatter do end_line = min(length(lines), line + 2) context_lines = - Enum.slice(lines, (start_line - 1)..(end_line - 1)) + lines + |> Enum.slice((start_line - 1)..(end_line - 1)) |> Enum.with_index(start_line) |> Enum.flat_map(fn {line_text, num} -> line_str = format_line_number(num) <> " │ " <> line_text @@ -101,8 +102,6 @@ defmodule Lua.VM.ErrorFormatter do end) "\n" <> Enum.join(context_lines) - else - nil end end @@ -115,10 +114,7 @@ defmodule Lua.VM.ErrorFormatter do defp format_stack_trace([]), do: nil defp format_stack_trace(call_stack) when is_list(call_stack) do - frames = - call_stack - |> Enum.map(&format_frame/1) - |> Enum.join("\n") + frames = Enum.map_join(call_stack, "\n", &format_frame/1) "\n\n" <> IO.ANSI.cyan() <> "Stack trace:" <> IO.ANSI.reset() <> "\n" <> frames end @@ -145,16 +141,12 @@ defmodule Lua.VM.ErrorFormatter do :call_non_function -> type_name = format_type_name(value_type) - suggestion( - "You can only call function values. Check that you're calling a function, not a #{type_name}." - ) + suggestion("You can only call function values. Check that you're calling a function, not a #{type_name}.") :index_non_table -> type_name = format_type_name(value_type) - suggestion( - "You can only index tables. Make sure the value you're indexing is a table, not a #{type_name}." - ) + suggestion("You can only index tables. Make sure the value you're indexing is a table, not a #{type_name}.") :arithmetic_type_error -> suggestion( diff --git a/lib/lua/vm/executor.ex b/lib/lua/vm/executor.ex index c3fd98f..ff9ed60 100644 --- a/lib/lua/vm/executor.ex +++ b/lib/lua/vm/executor.ex @@ -5,7 +5,11 @@ defmodule Lua.VM.Executor do Tail-recursive dispatch loop that executes instructions. """ - alias Lua.VM.{InternalError, State, TypeError, Value} + alias Lua.VM.InternalError + alias Lua.VM.RuntimeError + alias Lua.VM.State + alias Lua.VM.TypeError + alias Lua.VM.Value @doc """ Executes instructions with the given register file and state. @@ -111,13 +115,7 @@ defmodule Lua.VM.Executor do end # get_upvalue - defp do_execute( - [{:get_upvalue, dest, index} | rest], - regs, - {upvalues, _} = upvalue_context, - proto, - state - ) do + defp do_execute([{:get_upvalue, dest, index} | rest], regs, {upvalues, _} = upvalue_context, proto, state) do cell_ref = Enum.at(upvalues, index) value = Map.get(state.upvalue_cells, cell_ref) regs = put_elem(regs, dest, value) @@ -125,13 +123,7 @@ defmodule Lua.VM.Executor do end # set_upvalue - defp do_execute( - [{:set_upvalue, index, source} | rest], - regs, - {upvalues, _} = upvalue_context, - proto, - state - ) do + defp do_execute([{:set_upvalue, index, source} | rest], regs, {upvalues, _} = upvalue_context, proto, state) do cell_ref = Enum.at(upvalues, index) value = elem(regs, source) state = %{state | upvalue_cells: Map.put(state.upvalue_cells, cell_ref, value)} @@ -214,13 +206,7 @@ defmodule Lua.VM.Executor do end # while_loop - defp do_execute( - [{:while_loop, cond_body, test_reg, loop_body} | rest], - regs, - upvalues, - proto, - state - ) do + defp do_execute([{:while_loop, cond_body, test_reg, loop_body} | rest], regs, upvalues, proto, state) do # Execute condition {_results, regs, state} = do_execute(cond_body, regs, upvalues, proto, state) @@ -243,13 +229,7 @@ defmodule Lua.VM.Executor do end # repeat_loop - defp do_execute( - [{:repeat_loop, loop_body, cond_body, test_reg} | rest], - regs, - upvalues, - proto, - state - ) do + defp do_execute([{:repeat_loop, loop_body, cond_body, test_reg} | rest], regs, upvalues, proto, state) do # Execute body {_results, regs, state} = do_execute(loop_body, regs, upvalues, proto, state) @@ -307,13 +287,7 @@ defmodule Lua.VM.Executor do end # generic_for - generic for loop (for k, v in iterator do ... end) - defp do_execute( - [{:generic_for, base, var_regs, body} | rest], - regs, - upvalues, - proto, - state - ) do + defp do_execute([{:generic_for, base, var_regs, body} | rest], regs, upvalues, proto, state) do # Read iterator function, invariant state, control from internal registers iter_func = elem(regs, base) invariant_state = elem(regs, base + 1) @@ -354,13 +328,7 @@ defmodule Lua.VM.Executor do end # closure - create a closure value from a prototype, capturing upvalues - defp do_execute( - [{:closure, dest, proto_index} | rest], - regs, - {upvalues, open_upvalues}, - proto, - state - ) do + defp do_execute([{:closure, dest, proto_index} | rest], regs, {upvalues, open_upvalues}, proto, state) do nested_proto = Enum.at(proto.prototypes, proto_index) # Capture upvalues based on descriptors, reusing open upvalue cells when available @@ -392,13 +360,7 @@ defmodule Lua.VM.Executor do end # call - invoke a function value - defp do_execute( - [{:call, base, arg_count, result_count} | rest], - regs, - upvalue_context, - proto, - state - ) do + defp do_execute([{:call, base, arg_count, result_count} | rest], regs, upvalue_context, proto, state) do func_value = elem(regs, base) # Collect arguments from registers base+1..base+arg_count @@ -483,8 +445,7 @@ defmodule Lua.VM.Executor do other -> raise InternalError, - value: - "native function returned invalid result: #{inspect(other)}, expected {results, state}" + value: "native function returned invalid result: #{inspect(other)}, expected {results, state}" end nil -> @@ -807,13 +768,7 @@ defmodule Lua.VM.Executor do end # new_table - defp do_execute( - [{:new_table, dest, _array_hint, _hash_hint} | rest], - regs, - upvalues, - proto, - state - ) do + defp do_execute([{:new_table, dest, _array_hint, _hash_hint} | rest], regs, upvalues, proto, state) do {tref, state} = State.alloc_table(state) regs = put_elem(regs, dest, tref) do_execute(rest, regs, upvalues, proto, state) @@ -859,13 +814,7 @@ defmodule Lua.VM.Executor do end # set_table — table[R[key_reg]] = R[value_reg] - defp do_execute( - [{:set_table, table_reg, key_reg, value_reg} | rest], - regs, - upvalues, - proto, - state - ) do + defp do_execute([{:set_table, table_reg, key_reg, value_reg} | rest], regs, upvalues, proto, state) do {:tref, id} = elem(regs, table_reg) key = elem(regs, key_reg) value = elem(regs, value_reg) @@ -954,13 +903,7 @@ defmodule Lua.VM.Executor do end # set_field — table[name] = R[value_reg] - defp do_execute( - [{:set_field, table_reg, name, value_reg} | rest], - regs, - upvalues, - proto, - state - ) do + defp do_execute([{:set_field, table_reg, name, value_reg} | rest], regs, upvalues, proto, state) do {:tref, id} = elem(regs, table_reg) value = elem(regs, value_reg) table = Map.fetch!(state.tables, id) @@ -1011,13 +954,7 @@ defmodule Lua.VM.Executor do # set_list — bulk store: table[offset+i] = R[start+i-1] for i in 1..count # count == 0 means store all values from start until nil or end of tuple - defp do_execute( - [{:set_list, table_reg, start, count, offset} | rest], - regs, - upvalues, - proto, - state - ) do + defp do_execute([{:set_list, table_reg, start, count, offset} | rest], regs, upvalues, proto, state) do {:tref, id} = elem(regs, table_reg) state = @@ -1066,13 +1003,7 @@ defmodule Lua.VM.Executor do end # self — R[base+1] = R[obj_reg], R[base] = R[obj_reg]["method"] - defp do_execute( - [{:self, base, obj_reg, method_name} | rest], - regs, - upvalues, - proto, - state - ) do + defp do_execute([{:self, base, obj_reg, method_name} | rest], regs, upvalues, proto, state) do obj = elem(regs, obj_reg) {:tref, id} = obj table = Map.fetch!(state.tables, id) @@ -1381,7 +1312,7 @@ defmodule Lua.VM.Executor do # Note: Standard Lua 5.3 returns inf/-inf/nan for float division by zero, # but Elixir doesn't support creating these values easily, so we raise an error if nb == 0 or nb == 0.0 do - raise Lua.VM.RuntimeError, value: "attempt to divide by zero" + raise RuntimeError, value: "attempt to divide by zero" else na / nb end @@ -1398,7 +1329,7 @@ defmodule Lua.VM.Executor do with {:ok, na} <- to_number(a), {:ok, nb} <- to_number(b) do if trunc(nb) == 0 do - raise Lua.VM.RuntimeError, value: "attempt to divide by zero" + raise RuntimeError, value: "attempt to divide by zero" else div(trunc(na), trunc(nb)) end @@ -1415,7 +1346,7 @@ defmodule Lua.VM.Executor do with {:ok, na} <- to_number(a), {:ok, nb} <- to_number(b) do if trunc(nb) == 0 do - raise Lua.VM.RuntimeError, value: "attempt to perform modulo by zero" + raise RuntimeError, value: "attempt to perform modulo by zero" else rem(trunc(na), trunc(nb)) end diff --git a/lib/lua/vm/state.ex b/lib/lua/vm/state.ex index 0cbde21..467c59a 100644 --- a/lib/lua/vm/state.ex +++ b/lib/lua/vm/state.ex @@ -54,8 +54,7 @@ defmodule Lua.VM.State do where `args` is a list of Lua values and `results` is a list of return values. """ @spec register_function(t(), binary(), (list(), t() -> {list(), t()})) :: t() - def register_function(%__MODULE__{} = state, name, fun) - when is_binary(name) and is_function(fun) do + def register_function(%__MODULE__{} = state, name, fun) when is_binary(name) and is_function(fun) do set_global(state, name, {:native_func, fun}) end diff --git a/lib/lua/vm/stdlib.ex b/lib/lua/vm/stdlib.ex index 5d9e663..79c7b64 100644 --- a/lib/lua/vm/stdlib.ex +++ b/lib/lua/vm/stdlib.ex @@ -6,7 +6,13 @@ defmodule Lua.VM.Stdlib do scope when the standard library is installed. """ - alias Lua.VM.{AssertionError, State, Value} + alias Lua.VM.ArgumentError + alias Lua.VM.AssertionError + alias Lua.VM.Executor + alias Lua.VM.RuntimeError + alias Lua.VM.State + alias Lua.VM.TypeError + alias Lua.VM.Value @doc """ Installs the standard library into the given VM state. @@ -104,11 +110,11 @@ defmodule Lua.VM.Stdlib do # error(message) — raises a Lua runtime error defp lua_error([message | _], _state) do - raise Lua.VM.RuntimeError, value: message + raise RuntimeError, value: message end defp lua_error([], _state) do - raise Lua.VM.RuntimeError, value: nil + raise RuntimeError, value: nil end # assert(v [, message]) — raises if v is falsy @@ -133,18 +139,16 @@ defmodule Lua.VM.Stdlib do # pcall(f [, arg1, ...]) — calls function in protected mode # Returns true, result(s) on success or false, error_message on error defp lua_pcall([func | args], state) do - try do - {results, state} = Lua.VM.Executor.call_function(func, args, state) - {[true | results], state} - rescue - e in [Lua.VM.RuntimeError, AssertionError, Lua.VM.TypeError] -> - error_msg = extract_error_message(e) - {[false, error_msg], state} - - e -> - # Catch any other error - {[false, Exception.message(e)], state} - end + {results, state} = Executor.call_function(func, args, state) + {[true | results], state} + rescue + e in [RuntimeError, AssertionError, TypeError] -> + error_msg = extract_error_message(e) + {[false, error_msg], state} + + e -> + # Catch any other error + {[false, Exception.message(e)], state} end defp lua_pcall([], state), do: {[false, "bad argument #1 to 'pcall' (value expected)"], state} @@ -152,35 +156,33 @@ defmodule Lua.VM.Stdlib do # xpcall(f, msgh [, arg1, ...]) — calls function with message handler # Returns true, result(s) on success or false, handler_result on error defp lua_xpcall([func, handler | args], state) do - try do - {results, state} = Lua.VM.Executor.call_function(func, args, state) - {[true | results], state} - rescue - e in [Lua.VM.RuntimeError, AssertionError, Lua.VM.TypeError] -> - error_msg = extract_error_message(e) - - # Call the error handler - try do - {handler_results, state} = Lua.VM.Executor.call_function(handler, [error_msg], state) - {[false | handler_results], state} - rescue - _ -> - # If handler fails, return original error - {[false, error_msg], state} - end + {results, state} = Executor.call_function(func, args, state) + {[true | results], state} + rescue + e in [RuntimeError, AssertionError, TypeError] -> + error_msg = extract_error_message(e) + + # Call the error handler + try do + {handler_results, state} = Executor.call_function(handler, [error_msg], state) + {[false | handler_results], state} + rescue + _ -> + # If handler fails, return original error + {[false, error_msg], state} + end - e -> - # Catch any other error - error_msg = Exception.message(e) + e -> + # Catch any other error + error_msg = Exception.message(e) - try do - {handler_results, state} = Lua.VM.Executor.call_function(handler, [error_msg], state) - {[false | handler_results], state} - rescue - _ -> - {[false, error_msg], state} - end - end + try do + {handler_results, state} = Executor.call_function(handler, [error_msg], state) + {[false | handler_results], state} + rescue + _ -> + {[false, error_msg], state} + end end defp lua_xpcall(_, state), do: {[false, "bad argument to 'xpcall'"], state} @@ -314,12 +316,12 @@ defmodule Lua.VM.Stdlib do # Index 0 is invalid true -> - raise Lua.VM.RuntimeError, value: "bad argument #1 to 'select' (index out of range)" + raise RuntimeError, value: "bad argument #1 to 'select' (index out of range)" end end defp lua_select([non_valid | _], _state) do - raise Lua.VM.ArgumentError, + raise ArgumentError, function_name: "select", arg_num: 1, expected: "number or '#'", @@ -327,7 +329,7 @@ defmodule Lua.VM.Stdlib do end defp lua_select([], _state) do - raise Lua.VM.ArgumentError.value_expected("select", 1) + raise ArgumentError.value_expected("select", 1) end # setmetatable(table, metatable) — sets the metatable for a table @@ -343,7 +345,7 @@ defmodule Lua.VM.Stdlib do {[tref], state} _ -> - raise Lua.VM.ArgumentError, + raise ArgumentError, function_name: "setmetatable", arg_num: 2, expected: "nil or table" @@ -351,7 +353,7 @@ defmodule Lua.VM.Stdlib do end defp lua_setmetatable([non_table | _], _state) do - raise Lua.VM.ArgumentError, + raise ArgumentError, function_name: "setmetatable", arg_num: 1, expected: "table", @@ -359,7 +361,7 @@ defmodule Lua.VM.Stdlib do end defp lua_setmetatable([], _state) do - raise Lua.VM.ArgumentError.value_expected("setmetatable", 1) + raise ArgumentError.value_expected("setmetatable", 1) end # getmetatable(object) — returns the metatable of an object @@ -421,7 +423,7 @@ defmodule Lua.VM.Stdlib do end defp lua_require([non_string | _], _state) do - raise Lua.VM.ArgumentError, + raise ArgumentError, function_name: "require", arg_num: 1, expected: "string", @@ -429,7 +431,7 @@ defmodule Lua.VM.Stdlib do end defp lua_require([], _state) do - raise Lua.VM.ArgumentError.value_expected("require", 1) + raise ArgumentError.value_expected("require", 1) end # Load a module by searching the path @@ -441,7 +443,7 @@ defmodule Lua.VM.Stdlib do parse_and_execute_module(modname, file_path, content, state) {:error, :not_found} -> - raise Lua.VM.RuntimeError, + raise RuntimeError, value: "module '#{modname}' not found:\n\tno file '#{search_path}'" end end @@ -463,7 +465,7 @@ defmodule Lua.VM.Stdlib do {[result], state} else {:error, msg} -> - raise Lua.VM.RuntimeError, + raise RuntimeError, value: "error loading module '#{modname}' from file '#{file_path}':\n#{msg}" end end @@ -480,7 +482,7 @@ defmodule Lua.VM.Stdlib do # Get the package.loaded table reference defp get_package_loaded_ref(state) do with {:tref, pkg_id} <- Map.fetch!(state.globals, "package"), - package <- Map.fetch!(state.tables, pkg_id), + package = Map.fetch!(state.tables, pkg_id), {:tref, _loaded_id} = loaded_ref <- Map.fetch!(package.data, "loaded") do loaded_ref end diff --git a/lib/lua/vm/stdlib/string.ex b/lib/lua/vm/stdlib/string.ex index e466ddb..ea76ce8 100644 --- a/lib/lua/vm/stdlib/string.ex +++ b/lib/lua/vm/stdlib/string.ex @@ -96,7 +96,7 @@ defmodule Lua.VM.Stdlib.String do i = Enum.at(rest, 0) j = Enum.at(rest, 1) - unless is_integer(i) do + if !is_integer(i) do raise ArgumentError, function_name: "string.sub", arg_num: 2, @@ -133,7 +133,7 @@ defmodule Lua.VM.Stdlib.String do defp string_rep([str, n | rest], state) when is_binary(str) and is_integer(n) do sep = Enum.at(rest, 0, "") - unless is_binary(sep) do + if !is_binary(sep) do raise ArgumentError, function_name: "string.rep", arg_num: 3, @@ -145,9 +145,7 @@ defmodule Lua.VM.Stdlib.String do if n <= 0 do "" else - 1..n - |> Enum.map(fn _ -> str end) - |> Enum.join(sep) + Enum.map_join(1..n, sep, fn _ -> str end) end {[result], state} @@ -194,14 +192,14 @@ defmodule Lua.VM.Stdlib.String do i = Enum.at(rest, 0, 1) j = Enum.at(rest, 1, i) - unless is_integer(i) do + if !is_integer(i) do raise ArgumentError, function_name: "string.byte", arg_num: 2, expected: "number" end - unless is_integer(j) do + if !is_integer(j) do raise ArgumentError, function_name: "string.byte", arg_num: 3, @@ -219,8 +217,7 @@ defmodule Lua.VM.Stdlib.String do start_byte = max(0, start_idx) end_byte = min(len - 1, end_idx) - start_byte..end_byte - |> Enum.map(fn idx -> :binary.at(str, idx) end) + Enum.map(start_byte..end_byte, fn idx -> :binary.at(str, idx) end) end {bytes, state} @@ -362,7 +359,7 @@ defmodule Lua.VM.Stdlib.String do end defp format_float(val) when is_number(val) do - :io_lib.format("~.6f", [val / 1]) |> IO.iodata_to_binary() + "~.6f" |> :io_lib.format([val / 1]) |> IO.iodata_to_binary() end defp format_float(_) do diff --git a/lib/lua/vm/stdlib/table.ex b/lib/lua/vm/stdlib/table.ex index 35499e8..7a7b857 100644 --- a/lib/lua/vm/stdlib/table.ex +++ b/lib/lua/vm/stdlib/table.ex @@ -61,7 +61,8 @@ defmodule Lua.VM.Stdlib.Table do # Shift elements from pos to len one position up new_data = - Enum.reduce(len..pos, table.data, fn i, acc -> + len..pos + |> Enum.reduce(table.data, fn i, acc -> case Map.get(acc, i) do nil -> acc val -> Map.put(acc, i + 1, val) @@ -113,7 +114,8 @@ defmodule Lua.VM.Stdlib.Table do # Shift elements from pos+1 to len one position down new_data = - Enum.reduce((pos + 1)..len, Map.delete(table.data, pos), fn i, acc -> + (pos + 1)..len + |> Enum.reduce(Map.delete(table.data, pos), fn i, acc -> case Map.get(acc, i) do nil -> Map.delete(acc, i) val -> Map.put(Map.delete(acc, i), i - 1, val) @@ -145,7 +147,7 @@ defmodule Lua.VM.Stdlib.Table do i = Enum.at(rest, 1, 1) j = Enum.at(rest, 2, get_table_length(table)) - unless is_binary(sep) do + if !is_binary(sep) do raise ArgumentError, function_name: "table.concat", arg_num: 2, @@ -153,7 +155,7 @@ defmodule Lua.VM.Stdlib.Table do got: Util.typeof(sep) end - unless is_integer(i) do + if !is_integer(i) do raise ArgumentError, function_name: "table.concat", arg_num: 3, @@ -161,7 +163,7 @@ defmodule Lua.VM.Stdlib.Table do got: Util.typeof(i) end - unless is_integer(j) do + if !is_integer(j) do raise ArgumentError, function_name: "table.concat", arg_num: 4, @@ -243,7 +245,7 @@ defmodule Lua.VM.Stdlib.Table do data = args |> Enum.with_index(1) - |> Enum.into(%{}, fn {val, idx} -> {idx, val} end) + |> Map.new(fn {val, idx} -> {idx, val} end) |> Map.put("n", length(args)) {tref, state} = State.alloc_table(state, data) @@ -256,7 +258,7 @@ defmodule Lua.VM.Stdlib.Table do i = Enum.at(rest, 0, 1) j = Enum.at(rest, 1, get_table_length(table)) - unless is_integer(i) do + if !is_integer(i) do raise ArgumentError, function_name: "table.unpack", arg_num: 2, @@ -264,7 +266,7 @@ defmodule Lua.VM.Stdlib.Table do got: Util.typeof(i) end - unless is_integer(j) do + if !is_integer(j) do raise ArgumentError, function_name: "table.unpack", arg_num: 3, @@ -293,11 +295,10 @@ defmodule Lua.VM.Stdlib.Table do end # table.move(a1, f, e, t [, a2]) - defp table_move([{:tref, _} = tref1, f, e, t | rest], state) - when is_integer(f) and is_integer(e) and is_integer(t) do + defp table_move([{:tref, _} = tref1, f, e, t | rest], state) when is_integer(f) and is_integer(e) and is_integer(t) do tref2 = List.first(rest) || tref1 - unless match?({:tref, _}, tref2) do + if !match?({:tref, _}, tref2) do raise ArgumentError, function_name: "table.move", arg_num: 5, @@ -327,8 +328,7 @@ defmodule Lua.VM.Stdlib.Table do {[tref2], state} end - defp table_move([_tref1, f, e, t | _rest], _state) - when is_integer(f) and is_integer(e) do + defp table_move([_tref1, f, e, t | _rest], _state) when is_integer(f) and is_integer(e) do raise ArgumentError, function_name: "table.move", arg_num: 4, diff --git a/lib/lua/vm/value.ex b/lib/lua/vm/value.ex index 2304b3a..c20cfab 100644 --- a/lib/lua/vm/value.ex +++ b/lib/lua/vm/value.ex @@ -54,8 +54,7 @@ defmodule Lua.VM.Value do def to_string(v) when is_binary(v), do: v - def to_string({:tref, id}), - do: "table: 0x#{String.pad_leading(Integer.to_string(id, 16), 14, "0")}" + def to_string({:tref, id}), do: "table: 0x#{String.pad_leading(Integer.to_string(id, 16), 14, "0")}" def to_string({:lua_closure, _, _}), do: "function" def to_string({:native_func, _}), do: "function" @@ -70,24 +69,22 @@ defmodule Lua.VM.Value do def parse_number(str) do str = String.trim(str) - cond do - String.starts_with?(str, "0x") or String.starts_with?(str, "0X") -> - case Integer.parse(String.slice(str, 2..-1//1), 16) do - {n, ""} -> n - _ -> nil - end - - true -> - case Integer.parse(str) do - {n, ""} -> - n - - _ -> - case Float.parse(str) do - {f, ""} -> f - _ -> nil - end - end + if String.starts_with?(str, "0x") or String.starts_with?(str, "0X") do + case Integer.parse(String.slice(str, 2..-1//1), 16) do + {n, ""} -> n + _ -> nil + end + else + case Integer.parse(str) do + {n, ""} -> + n + + _ -> + case Float.parse(str) do + {f, ""} -> f + _ -> nil + end + end end end diff --git a/lib/mix/tasks/lua.get_tests.ex b/lib/mix/tasks/lua.get_tests.ex index 6e2c69e..8342b7a 100644 --- a/lib/mix/tasks/lua.get_tests.ex +++ b/lib/mix/tasks/lua.get_tests.ex @@ -1,4 +1,5 @@ defmodule Mix.Tasks.Lua.GetTests do + @shortdoc "Downloads the Lua 5.3 test suite" @moduledoc """ Downloads the official Lua 5.3 test suite. @@ -22,7 +23,6 @@ defmodule Mix.Tasks.Lua.GetTests do use Mix.Task - @shortdoc "Downloads the Lua 5.3 test suite" @default_version "5.3.4" @base_url "https://www.lua.org/tests" @@ -79,7 +79,8 @@ defmodule Mix.Tasks.Lua.GetTests do case System.cmd("tar", ["-xzf", tarball_path, "-C", dest_dir], stderr_to_stdout: true) do {_output, 0} -> # Move files from extracted directory to test_dir - File.ls!(extracted_dir) + extracted_dir + |> File.ls!() |> Enum.each(fn file -> src = Path.join(extracted_dir, file) dest = Path.join(dest_dir, file) @@ -101,8 +102,7 @@ defmodule Mix.Tasks.Lua.GetTests do defp remove_unnecessary_files(test_dir) do # Remove C code directories - we don't need them for testing our Elixir implementation - ["libs", "ltests"] - |> Enum.each(fn dir -> + Enum.each(["libs", "ltests"], fn dir -> path = Path.join(test_dir, dir) if File.exists?(path), do: File.rm_rf!(path) end) diff --git a/mix.exs b/mix.exs index 964f19c..ec2105b 100644 --- a/mix.exs +++ b/mix.exs @@ -63,7 +63,8 @@ defmodule Lua.MixProject do {:usage_rules, "~> 0.1", only: [:dev]}, {:ex_doc, "~> 0.38", only: :dev, runtime: false}, {:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false}, - {:stream_data, "~> 1.1", only: [:test]} + {:stream_data, "~> 1.1", only: [:test]}, + {:styler, "~> 1.10", only: [:dev, :test], runtime: false} ] end end diff --git a/mix.lock b/mix.lock index 44283a4..ae430a1 100644 --- a/mix.lock +++ b/mix.lock @@ -22,6 +22,7 @@ "sourceror": {:hex, :sourceror, "1.10.1", "325753ed460fe9fa34ebb4deda76d57b2e1507dcd78a5eb9e1c41bfb78b7cdfe", [:mix], [], "hexpm", "288f3079d93865cd1e3e20df5b884ef2cb440e0e03e8ae393624ee8a770ba588"}, "spitfire": {:hex, :spitfire, "0.3.2", "476b7b5151fd053a864dae7b5eaeed01811e8b2ff3f24f3c048af1c9dfee5e3d", [:mix], [], "hexpm", "014f7b8c6dd45d1e3b08103c7e61515a590efc872441cf3e933a20efa4b5c46c"}, "stream_data": {:hex, :stream_data, "1.2.0", "58dd3f9e88afe27dc38bef26fce0c84a9e7a96772b2925c7b32cd2435697a52b", [:mix], [], "hexpm", "eb5c546ee3466920314643edf68943a5b14b32d1da9fe01698dc92b73f89a9ed"}, + "styler": {:hex, :styler, "1.10.1", "9229050c978bfaaab1d94e8673843576d0127d48fe64824a30babde3d6342475", [:mix], [], "hexpm", "d86cbcc70e8ab424393af313d1d885931ba9dc7c383d7dd30f4ab255a8d39f73"}, "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"}, "text_diff": {:hex, :text_diff, "0.1.0", "1caf3175e11a53a9a139bc9339bd607c47b9e376b073d4571c031913317fecaa", [:mix], [], "hexpm", "d1ffaaecab338e49357b6daa82e435f877e0649041ace7755583a0ea3362dbd7"}, "usage_rules": {:hex, :usage_rules, "0.1.26", "19d38c8b9b5c35434eae44f7e4554caeb5f08037a1d45a6b059a9782543ac22e", [:mix], [{:igniter, ">= 0.6.6 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}], "hexpm", "9f0d203aa288e1b48318929066778ec26fc423fd51f08518c5b47f58ad5caca9"}, diff --git a/test/lua/api_test.exs b/test/lua/api_test.exs index 9a26d9b..fed7228 100644 --- a/test/lua/api_test.exs +++ b/test/lua/api_test.exs @@ -1,8 +1,6 @@ defmodule Lua.APITest do use ExUnit.Case, async: true - alias Lua - describe "install/3 callback" do test "it can modify global lua state" do assert [{module, _}] = diff --git a/test/lua/ast/builder_test.exs b/test/lua/ast/builder_test.exs index 3184030..d8780f7 100644 --- a/test/lua/ast/builder_test.exs +++ b/test/lua/ast/builder_test.exs @@ -2,7 +2,11 @@ defmodule Lua.AST.BuilderTest do use ExUnit.Case, async: true import Lua.AST.Builder - alias Lua.AST.{Chunk, Block, Expr, Statement} + + alias Lua.AST.Block + alias Lua.AST.Chunk + alias Lua.AST.Expr + alias Lua.AST.Statement describe "chunk and block" do test "creates a chunk" do diff --git a/test/lua/ast/meta_test.exs b/test/lua/ast/meta_test.exs index 526a5c0..09e34f1 100644 --- a/test/lua/ast/meta_test.exs +++ b/test/lua/ast/meta_test.exs @@ -245,7 +245,7 @@ defmodule Lua.AST.MetaTest do test "is a proper struct" do meta = %Meta{} - assert meta.__struct__ == Lua.AST.Meta + assert meta.__struct__ == Meta end end end diff --git a/test/lua/ast/pretty_printer_test.exs b/test/lua/ast/pretty_printer_test.exs index 7e80245..190203d 100644 --- a/test/lua/ast/pretty_printer_test.exs +++ b/test/lua/ast/pretty_printer_test.exs @@ -2,7 +2,12 @@ defmodule Lua.AST.PrettyPrinterTest do use ExUnit.Case, async: true import Lua.AST.Builder - alias Lua.{Parser, AST.PrettyPrinter, AST.Meta} + + alias Lua.AST.Block + alias Lua.AST.Chunk + alias Lua.AST.Meta + alias Lua.AST.PrettyPrinter + alias Lua.Parser describe "literals" do test "prints nil" do @@ -469,14 +474,14 @@ defmodule Lua.AST.PrettyPrinterTest do describe "round-trip" do test "can round-trip simple expressions" do original = "return 2 + 3\n" - {:ok, ast} = Lua.Parser.parse(original) + {:ok, ast} = Parser.parse(original) printed = PrettyPrinter.print(ast) assert printed == original end test "can round-trip local assignments" do original = "local x = 42\n" - {:ok, ast} = Lua.Parser.parse(original) + {:ok, ast} = Parser.parse(original) printed = PrettyPrinter.print(ast) assert printed == original end @@ -488,14 +493,14 @@ defmodule Lua.AST.PrettyPrinterTest do end """ - {:ok, ast} = Lua.Parser.parse(code) + {:ok, ast} = Parser.parse(code) printed = PrettyPrinter.print(ast) # Parse again to verify structure matches - {:ok, ast2} = Lua.Parser.parse(printed) + {:ok, ast2} = Parser.parse(printed) # Compare AST structures (ignoring meta) - assert ast.block.stmts |> length() == ast2.block.stmts |> length() + assert length(ast.block.stmts) == length(ast2.block.stmts) end end @@ -509,7 +514,7 @@ defmodule Lua.AST.PrettyPrinterTest do test "escapes double quotes" do ast = chunk([return_stmt([string("say \"hello\"")])]) result = PrettyPrinter.print(ast) - assert result == "return \"say \\\"hello\\\"\"\n" + assert result == ~s(return "say \\"hello\\""\n) end test "escapes tab character" do @@ -521,7 +526,7 @@ defmodule Lua.AST.PrettyPrinterTest do test "escapes all special characters together" do ast = chunk([return_stmt([string("line1\n\"quote\"\ttab\\back")])]) result = PrettyPrinter.print(ast) - assert result == "return \"line1\\n\\\"quote\\\"\\ttab\\\\back\"\n" + assert result == ~s(return "line1\\n\\"quote\\"\\ttab\\\\back"\n) end end @@ -538,7 +543,7 @@ defmodule Lua.AST.PrettyPrinterTest do test "prints concatenation" do ast = chunk([return_stmt([binop(:concat, string("hello"), string("world"))])]) - assert PrettyPrinter.print(ast) == "return \"hello\" .. \"world\"\n" + assert PrettyPrinter.print(ast) == ~s(return "hello" .. "world"\n) end test "prints equality" do @@ -582,7 +587,7 @@ defmodule Lua.AST.PrettyPrinterTest do ]) ]) - assert PrettyPrinter.print(ast) == "return \"a\" .. \"b\" .. \"c\"\n" + assert PrettyPrinter.print(ast) == ~s(return "a" .. "b" .. "c"\n) # ("a" .. "b") .. "c" should have parentheses ast = @@ -592,7 +597,7 @@ defmodule Lua.AST.PrettyPrinterTest do ]) ]) - assert PrettyPrinter.print(ast) == "return (\"a\" .. \"b\") .. \"c\"\n" + assert PrettyPrinter.print(ast) == ~s{return ("a" .. "b") .. "c"\n} end test "handles subtraction left-associativity" do @@ -1076,13 +1081,13 @@ defmodule Lua.AST.PrettyPrinterTest do # When passing a simple string name (not a list) alias Lua.AST.Statement - ast = %Lua.AST.Chunk{ - block: %Lua.AST.Block{ + ast = %Chunk{ + block: %Block{ stmts: [ %Statement.FuncDecl{ name: "simple", params: [], - body: %Lua.AST.Block{stmts: [return_stmt([])]}, + body: %Block{stmts: [return_stmt([])]}, is_method: false, meta: nil } @@ -1100,8 +1105,8 @@ defmodule Lua.AST.PrettyPrinterTest do # Create a BinOp with an invalid operator to test the default case alias Lua.AST.Expr - ast = %Lua.AST.Chunk{ - block: %Lua.AST.Block{ + ast = %Chunk{ + block: %Block{ stmts: [ return_stmt([ %Expr.BinOp{ @@ -1123,8 +1128,8 @@ defmodule Lua.AST.PrettyPrinterTest do # Create a UnOp with an invalid operator to test the default case alias Lua.AST.Expr - ast = %Lua.AST.Chunk{ - block: %Lua.AST.Block{ + ast = %Chunk{ + block: %Block{ stmts: [ return_stmt([ %Expr.UnOp{ @@ -1467,7 +1472,7 @@ defmodule Lua.AST.PrettyPrinterTest do [stmt | _] = ast.block.stmts comment = Meta.get_trailing_comment(stmt.meta) - assert comment != nil + assert comment assert comment.position.line == 1 assert comment.text == " inline" end @@ -1530,8 +1535,8 @@ defmodule Lua.AST.PrettyPrinterTest do comments2 = extract_all_comments(ast2) # Compare comment text (positions may differ due to formatting) - texts1 = Enum.map(comments1, & &1.text) |> Enum.sort() - texts2 = Enum.map(comments2, & &1.text) |> Enum.sort() + texts1 = comments1 |> Enum.map(& &1.text) |> Enum.sort() + texts2 = comments2 |> Enum.map(& &1.text) |> Enum.sort() assert texts1 == texts2, """ Comments not preserved through round-trip @@ -1544,8 +1549,7 @@ defmodule Lua.AST.PrettyPrinterTest do # Extract all comments from an AST defp extract_all_comments(node, acc \\ []) - defp extract_all_comments(%{meta: meta} = node, acc) - when is_struct(node) and not is_nil(meta) do + defp extract_all_comments(%{meta: meta} = node, acc) when is_struct(node) and not is_nil(meta) do leading = Meta.get_leading_comments(meta) trailing = Meta.get_trailing_comment(meta) trailing_list = if trailing, do: [trailing], else: [] diff --git a/test/lua/ast/walker_test.exs b/test/lua/ast/walker_test.exs index 50a545f..7a38c85 100644 --- a/test/lua/ast/walker_test.exs +++ b/test/lua/ast/walker_test.exs @@ -2,7 +2,11 @@ defmodule Lua.AST.WalkerTest do use ExUnit.Case, async: true import Lua.AST.Builder - alias Lua.AST.{Walker, Expr, Statement} + + alias Lua.AST.Chunk + alias Lua.AST.Expr + alias Lua.AST.Statement + alias Lua.AST.Walker describe "walk/2" do test "visits all nodes in pre-order" do @@ -23,7 +27,7 @@ defmodule Lua.AST.WalkerTest do # Should visit in pre-order: Chunk, Block, Local, BinOp, Number(2), Number(3) assert length(visited) == 6 - assert hd(visited).__struct__ == Lua.AST.Chunk + assert hd(visited).__struct__ == Chunk end test "visits all nodes in post-order" do @@ -48,7 +52,7 @@ defmodule Lua.AST.WalkerTest do # Should visit in post-order: children before parents # Last visited should be Chunk assert length(visited) == 6 - assert List.last(visited).__struct__ == Lua.AST.Chunk + assert List.last(visited).__struct__ == Chunk end test "walks through if statement with all branches" do @@ -699,9 +703,7 @@ defmodule Lua.AST.WalkerTest do # for i = 1, 10, 2 do print(i) end ast = chunk([ - for_num("i", number(1), number(10), [call_stmt(call(var("print"), [var("i")]))], - step: number(2) - ) + for_num("i", number(1), number(10), [call_stmt(call(var("print"), [var("i")]))], step: number(2)) ]) # Count numbers (start, limit, step) diff --git a/test/lua/compiler/integration_test.exs b/test/lua/compiler/integration_test.exs index d3d86be..27bfce8 100644 --- a/test/lua/compiler/integration_test.exs +++ b/test/lua/compiler/integration_test.exs @@ -1,7 +1,13 @@ defmodule Lua.Compiler.IntegrationTest do use ExUnit.Case, async: true - alias Lua.{Parser, Compiler, VM} + alias Lua.Compiler + alias Lua.Parser + alias Lua.VM + alias Lua.VM.AssertionError + alias Lua.VM.Stdlib + alias Lua.VM.TypeError + alias Lua.VM.Value describe "end-to-end compilation and execution" do test "return 42" do @@ -1174,8 +1180,7 @@ defmodule Lua.Compiler.IntegrationTest do assert {:ok, proto} = Compiler.compile(ast) state = - VM.State.new() - |> VM.State.register_function("double", fn [n], state -> {[n * 2], state} end) + VM.State.register_function(VM.State.new(), "double", fn [n], state -> {[n * 2], state} end) assert {:ok, [42], _state} = VM.execute(proto, state) end @@ -1187,8 +1192,7 @@ defmodule Lua.Compiler.IntegrationTest do assert {:ok, proto} = Compiler.compile(ast) state = - VM.State.new() - |> VM.State.register_function("add", fn args, state -> + VM.State.register_function(VM.State.new(), "add", fn args, state -> {[Enum.sum(args)], state} end) @@ -1202,8 +1206,7 @@ defmodule Lua.Compiler.IntegrationTest do assert {:ok, proto} = Compiler.compile(ast) state = - VM.State.new() - |> VM.State.register_function("get_answer", fn _args, state -> {[42], state} end) + VM.State.register_function(VM.State.new(), "get_answer", fn _args, state -> {[42], state} end) assert {:ok, [42], _state} = VM.execute(proto, state) end @@ -1218,8 +1221,7 @@ defmodule Lua.Compiler.IntegrationTest do assert {:ok, proto} = Compiler.compile(ast) state = - VM.State.new() - |> VM.State.register_function("set_x", fn [val], state -> + VM.State.register_function(VM.State.new(), "set_x", fn [val], state -> {[], VM.State.set_global(state, "x", val)} end) @@ -1236,8 +1238,7 @@ defmodule Lua.Compiler.IntegrationTest do assert {:ok, proto} = Compiler.compile(ast) state = - VM.State.new() - |> VM.State.register_function("get_field", fn [{:tref, id}, key], state -> + VM.State.register_function(VM.State.new(), "get_field", fn [{:tref, id}, key], state -> table = Map.fetch!(state.tables, id) {[Map.get(table.data, key)], state} end) @@ -1255,8 +1256,7 @@ defmodule Lua.Compiler.IntegrationTest do assert {:ok, proto} = Compiler.compile(ast) state = - VM.State.new() - |> VM.State.register_function("make_table", fn _args, state -> + VM.State.register_function(VM.State.new(), "make_table", fn _args, state -> {tref, state} = VM.State.alloc_table(state, %{"x" => 100}) {[tref], state} end) @@ -1270,7 +1270,7 @@ defmodule Lua.Compiler.IntegrationTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast) - assert_raise Lua.VM.TypeError, ~r/attempt to call a nil value/, fn -> + assert_raise TypeError, ~r/attempt to call a nil value/, fn -> VM.execute(proto) end end @@ -1284,7 +1284,7 @@ defmodule Lua.Compiler.IntegrationTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast) - assert_raise Lua.VM.TypeError, ~r/attempt to call a number value/, fn -> + assert_raise TypeError, ~r/attempt to call a number value/, fn -> VM.execute(proto) end end @@ -1292,7 +1292,7 @@ defmodule Lua.Compiler.IntegrationTest do describe "standard library" do setup do - state = Lua.VM.Stdlib.install(VM.State.new()) + state = Stdlib.install(VM.State.new()) {:ok, state: state} end @@ -1397,7 +1397,7 @@ defmodule Lua.Compiler.IntegrationTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast) - assert_raise Lua.VM.AssertionError, ~r/assertion failed: expected true/, fn -> + assert_raise AssertionError, ~r/assertion failed: expected true/, fn -> VM.execute(proto, state) end end @@ -1408,7 +1408,7 @@ defmodule Lua.Compiler.IntegrationTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast) - assert_raise Lua.VM.AssertionError, ~r/assertion failed: assertion failed!/, fn -> + assert_raise AssertionError, ~r/assertion failed: assertion failed!/, fn -> VM.execute(proto, state) end end @@ -1624,7 +1624,7 @@ defmodule Lua.Compiler.IntegrationTest do describe "generic for loops" do setup do - state = Lua.VM.Stdlib.install(VM.State.new()) + state = Stdlib.install(VM.State.new()) {:ok, state: state} end @@ -1704,8 +1704,8 @@ defmodule Lua.Compiler.IntegrationTest do describe "value encode/decode round-trip" do test "encode Elixir map as global, execute Lua, decode result" do # Encode an Elixir map into state as a global - state = Lua.VM.Stdlib.install(VM.State.new()) - {tref, state} = Lua.VM.Value.encode(%{x: 10, y: 20}, state) + state = Stdlib.install(VM.State.new()) + {tref, state} = Value.encode(%{x: 10, y: 20}, state) state = VM.State.set_global(state, "config", tref) # Execute Lua code that reads from the encoded table @@ -1716,8 +1716,8 @@ defmodule Lua.Compiler.IntegrationTest do end test "encode list as global, iterate in Lua, decode result" do - state = Lua.VM.Stdlib.install(VM.State.new()) - {tref, state} = Lua.VM.Value.encode([10, 20, 30], state) + state = Stdlib.install(VM.State.new()) + {tref, state} = Value.encode([10, 20, 30], state) state = VM.State.set_global(state, "items", tref) code = """ @@ -1734,7 +1734,7 @@ defmodule Lua.Compiler.IntegrationTest do end test "Lua produces table, decode to Elixir" do - state = Lua.VM.Stdlib.install(VM.State.new()) + state = Stdlib.install(VM.State.new()) code = """ local t = {a = 1, b = 2} @@ -1745,7 +1745,7 @@ defmodule Lua.Compiler.IntegrationTest do assert {:ok, proto} = Compiler.compile(ast) assert {:ok, [tref], state} = VM.execute(proto, state) - decoded = Lua.VM.Value.decode(tref, state) + decoded = Value.decode(tref, state) assert Enum.sort(decoded) == [{"a", 1}, {"b", 2}] end end diff --git a/test/lua/compiler/source_line_test.exs b/test/lua/compiler/source_line_test.exs index 6026cd3..b3cea46 100644 --- a/test/lua/compiler/source_line_test.exs +++ b/test/lua/compiler/source_line_test.exs @@ -1,7 +1,8 @@ defmodule Lua.Compiler.SourceLineTest do use ExUnit.Case, async: true - alias Lua.{Parser, Compiler} + alias Lua.Compiler + alias Lua.Parser describe "source line tracking" do test "emits source_line instructions before statements" do @@ -16,8 +17,7 @@ defmodule Lua.Compiler.SourceLineTest do # Check that source_line instructions are present source_line_instructions = - proto.instructions - |> Enum.filter(fn + Enum.filter(proto.instructions, fn {:source_line, _, _} -> true _ -> false end) diff --git a/test/lua/error_messages_test.exs b/test/lua/error_messages_test.exs index 00148bd..e09963e 100644 --- a/test/lua/error_messages_test.exs +++ b/test/lua/error_messages_test.exs @@ -1,8 +1,11 @@ defmodule Lua.ErrorMessagesTest do use ExUnit.Case, async: true - alias Lua.{Parser, Compiler, VM} + alias Lua.Compiler + alias Lua.Parser + alias Lua.VM alias Lua.VM.State + alias Lua.VM.TypeError describe "beautiful error messages" do test "calling nil value shows helpful error" do @@ -16,7 +19,7 @@ defmodule Lua.ErrorMessagesTest do state = State.new() - assert_raise Lua.VM.TypeError, fn -> + assert_raise TypeError, fn -> VM.execute(proto, state) end end @@ -33,7 +36,7 @@ defmodule Lua.ErrorMessagesTest do state = State.new() error = - assert_raise Lua.VM.TypeError, fn -> + assert_raise TypeError, fn -> VM.execute(proto, state) end @@ -52,7 +55,7 @@ defmodule Lua.ErrorMessagesTest do state = State.new() error = - assert_raise Lua.VM.TypeError, fn -> + assert_raise TypeError, fn -> VM.execute(proto, state) end @@ -79,7 +82,7 @@ defmodule Lua.ErrorMessagesTest do state = State.new() error = - assert_raise Lua.VM.TypeError, fn -> + assert_raise TypeError, fn -> VM.execute(proto, state) end @@ -99,7 +102,7 @@ defmodule Lua.ErrorMessagesTest do state = State.new() - assert_raise Lua.VM.TypeError, ~r/concatenate/, fn -> + assert_raise TypeError, ~r/concatenate/, fn -> VM.execute(proto, state) end end @@ -120,7 +123,7 @@ defmodule Lua.ErrorMessagesTest do state = State.new() error = - assert_raise Lua.VM.TypeError, fn -> + assert_raise TypeError, fn -> VM.execute(proto, state) end @@ -146,12 +149,12 @@ defmodule Lua.ErrorMessagesTest do state = State.new() error = - assert_raise Lua.VM.TypeError, fn -> + assert_raise TypeError, fn -> VM.execute(proto, state) end # Should have line information - assert error.line != nil + assert error.line assert error.line > 0 end @@ -179,7 +182,7 @@ defmodule Lua.ErrorMessagesTest do state = State.new() error = - assert_raise Lua.VM.TypeError, fn -> + assert_raise TypeError, fn -> VM.execute(proto, state) end diff --git a/test/lua/lexer_test.exs b/test/lua/lexer_test.exs index f850d37..1a0a4d5 100644 --- a/test/lua/lexer_test.exs +++ b/test/lua/lexer_test.exs @@ -1,8 +1,9 @@ defmodule Lua.LexerTest do use ExUnit.Case, async: true + alias Lua.Lexer - doctest Lua.Lexer + doctest Lexer describe "keywords" do test "tokenizes all Lua keywords" do @@ -67,7 +68,7 @@ defmodule Lua.LexerTest do test "tokenizes integers" do assert {:ok, [{:number, 0, _}, {:eof, _}]} = Lexer.tokenize("0") assert {:ok, [{:number, 42, _}, {:eof, _}]} = Lexer.tokenize("42") - assert {:ok, [{:number, 12345, _}, {:eof, _}]} = Lexer.tokenize("12345") + assert {:ok, [{:number, 12_345, _}, {:eof, _}]} = Lexer.tokenize("12345") end test "tokenizes floating point numbers" do @@ -292,8 +293,7 @@ defmodule Lua.LexerTest do assert {:ok, [{:comment, :single, " this is a comment", _}, {:eof, _}]} = Lexer.tokenize("-- this is a comment") - assert {:ok, - [{:identifier, "x", _}, {:comment, :single, " comment after code", _}, {:eof, _}]} = + assert {:ok, [{:identifier, "x", _}, {:comment, :single, " comment after code", _}, {:eof, _}]} = Lexer.tokenize("x -- comment after code") end diff --git a/test/lua/parser/comment_test.exs b/test/lua/parser/comment_test.exs index 2dd1633..d6db49b 100644 --- a/test/lua/parser/comment_test.exs +++ b/test/lua/parser/comment_test.exs @@ -1,7 +1,9 @@ defmodule Lua.Parser.CommentTest do use ExUnit.Case, async: true + + alias Lua.AST.Meta + alias Lua.AST.Statement alias Lua.Parser - alias Lua.AST.{Meta, Statement} describe "single-line comments as leading comments" do test "attaches comment before local statement" do @@ -82,7 +84,7 @@ defmodule Lua.Parser.CommentTest do assert %Statement.Local{meta: meta} = stmt comment = Meta.get_trailing_comment(meta) - assert comment != nil + assert comment assert comment.text == " The answer" assert comment.type == :single end @@ -159,7 +161,7 @@ defmodule Lua.Parser.CommentTest do assert hd(leading).text == " Leading comment" trailing = Meta.get_trailing_comment(stmt.meta) - assert trailing != nil + assert trailing assert trailing.text == " Trailing comment" end end diff --git a/test/lua/parser/error_test.exs b/test/lua/parser/error_test.exs index 754f17a..3e46555 100644 --- a/test/lua/parser/error_test.exs +++ b/test/lua/parser/error_test.exs @@ -3,6 +3,7 @@ defmodule Lua.Parser.ErrorTest do Tests for parser error messages, including formatting and suggestions. """ use ExUnit.Case, async: true + alias Lua.Parser describe "syntax errors" do diff --git a/test/lua/parser/error_unit_test.exs b/test/lua/parser/error_unit_test.exs index c9d566d..8bc321b 100644 --- a/test/lua/parser/error_unit_test.exs +++ b/test/lua/parser/error_unit_test.exs @@ -335,7 +335,7 @@ defmodule Lua.Parser.ErrorUnitTest do assert String.contains?(error.message, "Unexpected end of input") assert String.contains?(error.message, "while parsing expression") assert error.position == nil - assert error.suggestion != nil + assert error.suggestion end end @@ -441,9 +441,7 @@ defmodule Lua.Parser.ErrorUnitTest do position = %{line: 1, column: 5, byte_offset: 0} error = - Error.new(:expected_token, "Expected something", position, - suggestion: "Try adding a semicolon" - ) + Error.new(:expected_token, "Expected something", position, suggestion: "Try adding a semicolon") formatted = Error.format(error, source_code) diff --git a/test/lua/parser/expr_test.exs b/test/lua/parser/expr_test.exs index cf941b3..8572df9 100644 --- a/test/lua/parser/expr_test.exs +++ b/test/lua/parser/expr_test.exs @@ -1,7 +1,9 @@ defmodule Lua.Parser.ExprTest do use ExUnit.Case, async: true + + alias Lua.AST.Expr + alias Lua.AST.Statement alias Lua.Parser - alias Lua.AST.{Expr, Statement} # Helper to extract the returned expression from "return expr" defp parse_return_expr(code) do diff --git a/test/lua/parser/pratt_test.exs b/test/lua/parser/pratt_test.exs index 778eb00..96940cf 100644 --- a/test/lua/parser/pratt_test.exs +++ b/test/lua/parser/pratt_test.exs @@ -1,5 +1,6 @@ defmodule Lua.Parser.PrattTest do use ExUnit.Case, async: true + alias Lua.Parser.Pratt describe "binding_power/1" do diff --git a/test/lua/parser/precedence_test.exs b/test/lua/parser/precedence_test.exs index ba9e925..85e7784 100644 --- a/test/lua/parser/precedence_test.exs +++ b/test/lua/parser/precedence_test.exs @@ -1,7 +1,8 @@ defmodule Lua.Parser.PrecedenceTest do use ExUnit.Case, async: true - alias Lua.Parser + alias Lua.AST.Expr + alias Lua.Parser describe "operator precedence" do test "or has lowest precedence" do diff --git a/test/lua/parser/recovery_test.exs b/test/lua/parser/recovery_test.exs index 2ab5914..aa3b823 100644 --- a/test/lua/parser/recovery_test.exs +++ b/test/lua/parser/recovery_test.exs @@ -1,8 +1,8 @@ defmodule Lua.Parser.RecoveryTest do use ExUnit.Case, async: true - alias Lua.Parser.Recovery alias Lua.Parser.Error + alias Lua.Parser.Recovery describe "recover_at_statement/2" do test "recovers at semicolon" do diff --git a/test/lua/parser/statement_test.exs b/test/lua/parser/statement_test.exs index b631193..c1093a0 100644 --- a/test/lua/parser/statement_test.exs +++ b/test/lua/parser/statement_test.exs @@ -1,7 +1,9 @@ defmodule Lua.Parser.StatementTest do use ExUnit.Case, async: true + + alias Lua.AST.Expr + alias Lua.AST.Statement alias Lua.Parser - alias Lua.AST.{Statement, Expr} describe "local variable declarations" do test "parses local without initialization" do diff --git a/test/lua/runtime_exception_test.exs b/test/lua/runtime_exception_test.exs index 2b09cac..d4a52a9 100644 --- a/test/lua/runtime_exception_test.exs +++ b/test/lua/runtime_exception_test.exs @@ -1,6 +1,8 @@ defmodule Lua.RuntimeExceptionTest do use ExUnit.Case, async: true + alias Lua.RuntimeException + alias Lua.VM.State describe "exception/1 with {:lua_error, error, state}" do test "formats simple lua error with stacktrace" do @@ -77,7 +79,7 @@ defmodule Lua.RuntimeExceptionTest do describe "exception/1 with {:api_error, details, state}" do test "creates exception with api error message" do - state = Lua.VM.State.new() + state = State.new() details = "invalid function call" exception = RuntimeException.exception({:api_error, details, state}) @@ -88,7 +90,7 @@ defmodule Lua.RuntimeExceptionTest do end test "handles complex api error details" do - state = Lua.VM.State.new() + state = State.new() details = "function returned invalid type: expected table, got nil" exception = RuntimeException.exception({:api_error, details, state}) diff --git a/test/lua/vm/arithmetic_test.exs b/test/lua/vm/arithmetic_test.exs index d207a9e..a88009b 100644 --- a/test/lua/vm/arithmetic_test.exs +++ b/test/lua/vm/arithmetic_test.exs @@ -1,8 +1,13 @@ defmodule Lua.VM.ArithmeticTest do use ExUnit.Case, async: true - alias Lua.{Parser, Compiler, VM} + alias Lua.Compiler + alias Lua.Parser + alias Lua.VM + alias Lua.VM.RuntimeError alias Lua.VM.State + alias Lua.VM.Stdlib + alias Lua.VM.TypeError describe "arithmetic type checking" do test "addition with numbers works" do @@ -14,7 +19,7 @@ defmodule Lua.VM.ArithmeticTest do end test "addition with string numbers coerces" do - code = "return \"5\" + \"3\"" + code = ~s(return "5" + "3") assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") state = State.new() @@ -27,7 +32,7 @@ defmodule Lua.VM.ArithmeticTest do assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") state = State.new() - assert_raise Lua.VM.TypeError, fn -> + assert_raise TypeError, fn -> VM.execute(proto, state) end end @@ -38,7 +43,7 @@ defmodule Lua.VM.ArithmeticTest do assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") state = State.new() - assert_raise Lua.VM.TypeError, fn -> + assert_raise TypeError, fn -> VM.execute(proto, state) end end @@ -49,7 +54,7 @@ defmodule Lua.VM.ArithmeticTest do assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") state = State.new() - assert_raise Lua.VM.TypeError, fn -> + assert_raise TypeError, fn -> VM.execute(proto, state) end end @@ -64,7 +69,7 @@ defmodule Lua.VM.ArithmeticTest do assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") state = State.new() - assert_raise Lua.VM.TypeError, fn -> + assert_raise TypeError, fn -> VM.execute(proto, state) end end @@ -75,7 +80,7 @@ defmodule Lua.VM.ArithmeticTest do assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") state = State.new() - assert_raise Lua.VM.TypeError, fn -> + assert_raise TypeError, fn -> VM.execute(proto, state) end end @@ -99,7 +104,7 @@ defmodule Lua.VM.ArithmeticTest do assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") state = State.new() - assert_raise Lua.VM.TypeError, fn -> + assert_raise TypeError, fn -> VM.execute(proto, state) end end @@ -114,7 +119,7 @@ defmodule Lua.VM.ArithmeticTest do # Note: Standard Lua 5.3 returns inf for this case, but we raise an error # because Elixir doesn't easily support creating inf/nan values - assert_raise Lua.VM.RuntimeError, ~r/divide by zero/, fn -> + assert_raise RuntimeError, ~r/divide by zero/, fn -> VM.execute(proto, state) end end @@ -125,7 +130,7 @@ defmodule Lua.VM.ArithmeticTest do assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") state = State.new() - assert_raise Lua.VM.RuntimeError, ~r/divide by zero/, fn -> + assert_raise RuntimeError, ~r/divide by zero/, fn -> VM.execute(proto, state) end end @@ -136,7 +141,7 @@ defmodule Lua.VM.ArithmeticTest do assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") state = State.new() - assert_raise Lua.VM.RuntimeError, ~r/divide by zero/, fn -> + assert_raise RuntimeError, ~r/divide by zero/, fn -> VM.execute(proto, state) end end @@ -147,7 +152,7 @@ defmodule Lua.VM.ArithmeticTest do assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") state = State.new() - assert_raise Lua.VM.RuntimeError, ~r/modulo by zero/, fn -> + assert_raise RuntimeError, ~r/modulo by zero/, fn -> VM.execute(proto, state) end end @@ -163,7 +168,7 @@ defmodule Lua.VM.ArithmeticTest do end test "comparing strings works" do - code = "return \"abc\" < \"def\", \"abc\" <= \"abc\", \"xyz\" > \"abc\"" + code = ~s(return "abc" < "def", "abc" <= "abc", "xyz" > "abc") assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") state = State.new() @@ -176,7 +181,7 @@ defmodule Lua.VM.ArithmeticTest do assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") state = State.new() - assert_raise Lua.VM.TypeError, fn -> + assert_raise TypeError, fn -> VM.execute(proto, state) end end @@ -187,7 +192,7 @@ defmodule Lua.VM.ArithmeticTest do assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") state = State.new() - assert_raise Lua.VM.TypeError, fn -> + assert_raise TypeError, fn -> VM.execute(proto, state) end end @@ -202,7 +207,7 @@ defmodule Lua.VM.ArithmeticTest do assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") state = State.new() - assert_raise Lua.VM.TypeError, fn -> + assert_raise TypeError, fn -> VM.execute(proto, state) end end @@ -231,7 +236,7 @@ defmodule Lua.VM.ArithmeticTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [false, err], _state} = VM.execute(proto, state) assert is_binary(err) assert err =~ "arithmetic" @@ -248,7 +253,7 @@ defmodule Lua.VM.ArithmeticTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [false, err], _state} = VM.execute(proto, state) assert is_binary(err) assert err =~ "divide by zero" @@ -265,7 +270,7 @@ defmodule Lua.VM.ArithmeticTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [false, err], _state} = VM.execute(proto, state) assert is_binary(err) assert err =~ "compare" diff --git a/test/lua/vm/call_stack_test.exs b/test/lua/vm/call_stack_test.exs index c481064..f188ff5 100644 --- a/test/lua/vm/call_stack_test.exs +++ b/test/lua/vm/call_stack_test.exs @@ -1,7 +1,9 @@ defmodule Lua.VM.CallStackTest do use ExUnit.Case, async: true - alias Lua.{Parser, Compiler, VM} + alias Lua.Compiler + alias Lua.Parser + alias Lua.VM alias Lua.VM.State describe "call stack tracking" do diff --git a/test/lua/vm/metatable_test.exs b/test/lua/vm/metatable_test.exs index 5dbd616..252f346 100644 --- a/test/lua/vm/metatable_test.exs +++ b/test/lua/vm/metatable_test.exs @@ -1,8 +1,12 @@ defmodule Lua.VM.MetatableTest do use ExUnit.Case, async: true - alias Lua.{Compiler, Parser, VM} + alias Lua.Compiler + alias Lua.Parser + alias Lua.VM + alias Lua.VM.ArgumentError alias Lua.VM.State + alias Lua.VM.Stdlib describe "metatable basics" do test "setmetatable and getmetatable" do @@ -16,7 +20,7 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [20], _state} = VM.execute(proto, state) end @@ -29,7 +33,7 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [nil], _state} = VM.execute(proto, state) end @@ -44,7 +48,7 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [10, 20, 30], _state} = VM.execute(proto, state) end @@ -59,7 +63,7 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) # t.y should be 15 (from t), not 20 (from __index) assert {:ok, [10, 15, 30], _state} = VM.execute(proto, state) @@ -75,7 +79,7 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [10], _state} = VM.execute(proto, state) end @@ -91,7 +95,7 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) # After setting metatable to nil, t.y should be nil assert {:ok, [10, nil], _state} = VM.execute(proto, state) @@ -104,9 +108,9 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) - assert_raise Lua.VM.ArgumentError, fn -> + assert_raise ArgumentError, fn -> VM.execute(proto, state) end end @@ -119,9 +123,9 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) - assert_raise Lua.VM.ArgumentError, fn -> + assert_raise ArgumentError, fn -> VM.execute(proto, state) end end @@ -133,9 +137,9 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) - assert_raise Lua.VM.ArgumentError, fn -> + assert_raise ArgumentError, fn -> VM.execute(proto, state) end end @@ -153,7 +157,7 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) # t.y and t.z should go to storage, not t assert {:ok, [10, nil, 20, 30], _state} = VM.execute(proto, state) @@ -172,7 +176,7 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) # t.y already exists, so it gets updated in t (not storage) # t.z doesn't exist, so it goes to storage @@ -198,7 +202,7 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [30], _state} = VM.execute(proto, state) end @@ -219,7 +223,7 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [20], _state} = VM.execute(proto, state) end @@ -240,7 +244,7 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [30], _state} = VM.execute(proto, state) end @@ -260,7 +264,7 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [-42], _state} = VM.execute(proto, state) end @@ -285,7 +289,7 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [true, false], _state} = VM.execute(proto, state) end @@ -311,7 +315,7 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) # Different metamethods, so falls back to reference equality (false) assert {:ok, [false], _state} = VM.execute(proto, state) @@ -333,7 +337,7 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [true, false], _state} = VM.execute(proto, state) end @@ -356,7 +360,7 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [true, true, false], _state} = VM.execute(proto, state) end @@ -380,7 +384,7 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["Hello World"], _state} = VM.execute(proto, state) end @@ -399,7 +403,7 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [42], _state} = VM.execute(proto, state) end @@ -409,9 +413,9 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) - assert_raise Lua.VM.ArgumentError, fn -> + assert_raise ArgumentError, fn -> VM.execute(proto, state) end end @@ -421,9 +425,9 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) - assert_raise Lua.VM.ArgumentError, fn -> + assert_raise ArgumentError, fn -> VM.execute(proto, state) end end @@ -433,9 +437,9 @@ defmodule Lua.VM.MetatableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) - assert_raise Lua.VM.ArgumentError, fn -> + assert_raise ArgumentError, fn -> VM.execute(proto, state) end end diff --git a/test/lua/vm/pcall_test.exs b/test/lua/vm/pcall_test.exs index 06fdf0f..d39c415 100644 --- a/test/lua/vm/pcall_test.exs +++ b/test/lua/vm/pcall_test.exs @@ -1,8 +1,11 @@ defmodule Lua.VM.PcallTest do use ExUnit.Case, async: true - alias Lua.{Parser, Compiler, VM} + alias Lua.Compiler + alias Lua.Parser + alias Lua.VM alias Lua.VM.State + alias Lua.VM.Stdlib describe "pcall and xpcall" do test "pcall success - return entire result table" do @@ -17,7 +20,7 @@ defmodule Lua.VM.PcallTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, results, _state} = VM.execute(proto, state) # Should return [true, 42] @@ -36,7 +39,7 @@ defmodule Lua.VM.PcallTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, results, _state} = VM.execute(proto, state) assert [false, err] = results @@ -56,7 +59,7 @@ defmodule Lua.VM.PcallTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, results, _state} = VM.execute(proto, state) assert [true, 30] = results @@ -75,7 +78,7 @@ defmodule Lua.VM.PcallTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, results, _state} = VM.execute(proto, state) assert [false, err] = results @@ -99,7 +102,7 @@ defmodule Lua.VM.PcallTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, results, _state} = VM.execute(proto, state) assert [false, handled] = results diff --git a/test/lua/vm/stdlib/math_test.exs b/test/lua/vm/stdlib/math_test.exs index fed0b51..935ce71 100644 --- a/test/lua/vm/stdlib/math_test.exs +++ b/test/lua/vm/stdlib/math_test.exs @@ -1,15 +1,18 @@ defmodule Lua.VM.Stdlib.MathTest do use ExUnit.Case, async: true - alias Lua.{Compiler, Parser, VM} + alias Lua.Compiler + alias Lua.Parser + alias Lua.VM alias Lua.VM.State + alias Lua.VM.Stdlib describe "math library" do test "math.abs returns absolute value" do code = "return math.abs(-5), math.abs(3.5), math.abs(0)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [5, 3.5, 0], _state} = VM.execute(proto, state) end @@ -18,7 +21,7 @@ defmodule Lua.VM.Stdlib.MathTest do code = "return math.ceil(3.2), math.ceil(-3.8), math.ceil(5)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [4.0, -3.0, 5.0], _state} = VM.execute(proto, state) end @@ -27,7 +30,7 @@ defmodule Lua.VM.Stdlib.MathTest do code = "return math.floor(3.8), math.floor(-3.2), math.floor(5)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [3.0, -4.0, 5.0], _state} = VM.execute(proto, state) end @@ -36,7 +39,7 @@ defmodule Lua.VM.Stdlib.MathTest do code = "return math.max(1, 5, 3), math.max(-2, -8)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [5, -2], _state} = VM.execute(proto, state) end @@ -45,7 +48,7 @@ defmodule Lua.VM.Stdlib.MathTest do code = "return math.min(1, 5, 3), math.min(-2, -8)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [1, -8], _state} = VM.execute(proto, state) end @@ -54,7 +57,7 @@ defmodule Lua.VM.Stdlib.MathTest do code = "return math.sqrt(16), math.sqrt(2)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [result1, result2], _state} = VM.execute(proto, state) assert result1 == 4.0 @@ -65,7 +68,7 @@ defmodule Lua.VM.Stdlib.MathTest do code = "return math.pi" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [pi], _state} = VM.execute(proto, state) assert_in_delta pi, 3.14159265, 0.00001 @@ -75,7 +78,7 @@ defmodule Lua.VM.Stdlib.MathTest do code = "return math.sin(0), math.sin(math.pi / 2)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [sin0, sin_pi_2], _state} = VM.execute(proto, state) assert_in_delta sin0, 0.0, 0.00001 @@ -86,7 +89,7 @@ defmodule Lua.VM.Stdlib.MathTest do code = "return math.cos(0), math.cos(math.pi)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [cos0, cos_pi], _state} = VM.execute(proto, state) assert_in_delta cos0, 1.0, 0.00001 @@ -97,7 +100,7 @@ defmodule Lua.VM.Stdlib.MathTest do code = "return math.tan(0), math.tan(math.pi / 4)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [tan0, tan_pi_4], _state} = VM.execute(proto, state) assert_in_delta tan0, 0.0, 0.00001 @@ -108,7 +111,7 @@ defmodule Lua.VM.Stdlib.MathTest do code = "return math.exp(0), math.exp(1)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [exp0, exp1], _state} = VM.execute(proto, state) assert_in_delta exp0, 1.0, 0.00001 @@ -119,7 +122,7 @@ defmodule Lua.VM.Stdlib.MathTest do code = "return math.log(1), math.log(10, 10), math.log(8, 2)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [log1, log10, log8], _state} = VM.execute(proto, state) assert_in_delta log1, 0.0, 0.00001 @@ -133,7 +136,7 @@ defmodule Lua.VM.Stdlib.MathTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [5, 5, nil, nil], _state} = VM.execute(proto, state) end @@ -142,7 +145,7 @@ defmodule Lua.VM.Stdlib.MathTest do code = "return math.type(5), math.type(5.5), math.type('str')" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["integer", "float", nil], _state} = VM.execute(proto, state) end @@ -151,7 +154,7 @@ defmodule Lua.VM.Stdlib.MathTest do code = "return math.huge > 1e100" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [true], _state} = VM.execute(proto, state) end @@ -160,7 +163,7 @@ defmodule Lua.VM.Stdlib.MathTest do code = "return math.maxinteger, math.mininteger" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [9_223_372_036_854_775_807, -9_223_372_036_854_775_808], _state} = VM.execute(proto, state) @@ -177,7 +180,7 @@ defmodule Lua.VM.Stdlib.MathTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [r1, r2, r3], _state} = VM.execute(proto, state) # r1 should be in [0, 1) diff --git a/test/lua/vm/stdlib/table_test.exs b/test/lua/vm/stdlib/table_test.exs index e1c47ed..8f0be6d 100644 --- a/test/lua/vm/stdlib/table_test.exs +++ b/test/lua/vm/stdlib/table_test.exs @@ -1,8 +1,11 @@ defmodule Lua.VM.Stdlib.TableTest do use ExUnit.Case, async: true - alias Lua.{Compiler, Parser, VM} + alias Lua.Compiler + alias Lua.Parser + alias Lua.VM alias Lua.VM.State + alias Lua.VM.Stdlib describe "table library" do test "table.insert appends to end" do @@ -14,7 +17,7 @@ defmodule Lua.VM.Stdlib.TableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [1, 2, 3, 4], _state} = VM.execute(proto, state) end @@ -28,7 +31,7 @@ defmodule Lua.VM.Stdlib.TableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [1, 2, 3, 4], _state} = VM.execute(proto, state) end @@ -43,7 +46,7 @@ defmodule Lua.VM.Stdlib.TableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [1, 2, 3, nil], _state} = VM.execute(proto, state) end @@ -57,7 +60,7 @@ defmodule Lua.VM.Stdlib.TableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [1, 3, 4, nil], _state} = VM.execute(proto, state) end @@ -70,7 +73,7 @@ defmodule Lua.VM.Stdlib.TableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["1, 2, 3, 4"], _state} = VM.execute(proto, state) end @@ -83,7 +86,7 @@ defmodule Lua.VM.Stdlib.TableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["2-3-4"], _state} = VM.execute(proto, state) end @@ -96,7 +99,7 @@ defmodule Lua.VM.Stdlib.TableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [1, 2, 3, 3], _state} = VM.execute(proto, state) end @@ -109,7 +112,7 @@ defmodule Lua.VM.Stdlib.TableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [10, 20, 30, 40], _state} = VM.execute(proto, state) end @@ -122,7 +125,7 @@ defmodule Lua.VM.Stdlib.TableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [20, 30, 40], _state} = VM.execute(proto, state) end @@ -136,7 +139,7 @@ defmodule Lua.VM.Stdlib.TableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [1, 1, 2, 3], _state} = VM.execute(proto, state) end @@ -151,7 +154,7 @@ defmodule Lua.VM.Stdlib.TableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [2, 3, 4], _state} = VM.execute(proto, state) end @@ -165,7 +168,7 @@ defmodule Lua.VM.Stdlib.TableTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [1, 2, 1, 2, 3], _state} = VM.execute(proto, state) end diff --git a/test/lua/vm/stdlib/util_test.exs b/test/lua/vm/stdlib/util_test.exs index 6c81f0e..5cd5bfe 100644 --- a/test/lua/vm/stdlib/util_test.exs +++ b/test/lua/vm/stdlib/util_test.exs @@ -2,8 +2,8 @@ defmodule Lua.VM.Stdlib.UtilTest do use ExUnit.Case, async: true use ExUnitProperties - alias Lua.VM.Stdlib.Util alias Lua.VM.State + alias Lua.VM.Stdlib.Util describe "typeof/1" do test "returns 'nil' for nil" do diff --git a/test/lua/vm/string_test.exs b/test/lua/vm/string_test.exs index ce51d08..43159c7 100644 --- a/test/lua/vm/string_test.exs +++ b/test/lua/vm/string_test.exs @@ -2,15 +2,19 @@ defmodule Lua.VM.StringTest do use ExUnit.Case, async: true use ExUnitProperties - alias Lua.{Parser, Compiler, VM} + alias Lua.Compiler + alias Lua.Parser + alias Lua.VM + alias Lua.VM.ArgumentError alias Lua.VM.State + alias Lua.VM.Stdlib describe "string.lower and string.upper" do test "string.lower converts to lowercase" do code = "return string.lower(\"HELLO World\")" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["hello world"], _state} = VM.execute(proto, state) end @@ -18,7 +22,7 @@ defmodule Lua.VM.StringTest do code = "return string.upper(\"hello World\")" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["HELLO WORLD"], _state} = VM.execute(proto, state) end @@ -26,9 +30,9 @@ defmodule Lua.VM.StringTest do code = "return string.lower(123)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) - assert_raise Lua.VM.ArgumentError, ~r/string expected/, fn -> + assert_raise ArgumentError, ~r/string expected/, fn -> VM.execute(proto, state) end end @@ -39,7 +43,7 @@ defmodule Lua.VM.StringTest do code = "return string.len(\"hello\")" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [5], _state} = VM.execute(proto, state) end @@ -47,7 +51,7 @@ defmodule Lua.VM.StringTest do code = "return string.len(\"\")" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [0], _state} = VM.execute(proto, state) end end @@ -57,7 +61,7 @@ defmodule Lua.VM.StringTest do code = "return string.sub(\"hello world\", 7, 11)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["world"], _state} = VM.execute(proto, state) end @@ -65,7 +69,7 @@ defmodule Lua.VM.StringTest do code = "return string.sub(\"hello\", -4, -2)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["ell"], _state} = VM.execute(proto, state) end @@ -73,7 +77,7 @@ defmodule Lua.VM.StringTest do code = "return string.sub(\"hello world\", 7)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["world"], _state} = VM.execute(proto, state) end @@ -81,7 +85,7 @@ defmodule Lua.VM.StringTest do code = "return string.sub(\"hello\", 10, 20)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [""], _state} = VM.execute(proto, state) end end @@ -91,15 +95,15 @@ defmodule Lua.VM.StringTest do code = "return string.rep(\"ha\", 3)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["hahaha"], _state} = VM.execute(proto, state) end test "string.rep with separator" do - code = "return string.rep(\"ha\", 3, \"-\")" + code = ~s{return string.rep("ha", 3, "-")} assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["ha-ha-ha"], _state} = VM.execute(proto, state) end @@ -107,7 +111,7 @@ defmodule Lua.VM.StringTest do code = "return string.rep(\"ha\", 0)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [""], _state} = VM.execute(proto, state) end end @@ -117,7 +121,7 @@ defmodule Lua.VM.StringTest do code = "return string.reverse(\"hello\")" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["olleh"], _state} = VM.execute(proto, state) end @@ -125,7 +129,7 @@ defmodule Lua.VM.StringTest do code = "return string.reverse(\"\")" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [""], _state} = VM.execute(proto, state) end end @@ -135,7 +139,7 @@ defmodule Lua.VM.StringTest do code = "return string.byte(\"A\")" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [65], _state} = VM.execute(proto, state) end @@ -143,7 +147,7 @@ defmodule Lua.VM.StringTest do code = "return string.byte(\"hello\", 2)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [101], _state} = VM.execute(proto, state) end @@ -151,7 +155,7 @@ defmodule Lua.VM.StringTest do code = "return string.byte(\"hello\", 1, 3)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [104, 101, 108], _state} = VM.execute(proto, state) end @@ -159,7 +163,7 @@ defmodule Lua.VM.StringTest do code = "return string.byte(\"hello\", -1)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [111], _state} = VM.execute(proto, state) end end @@ -169,7 +173,7 @@ defmodule Lua.VM.StringTest do code = "return string.char(72, 101, 108, 108, 111)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["Hello"], _state} = VM.execute(proto, state) end @@ -177,7 +181,7 @@ defmodule Lua.VM.StringTest do code = "return string.char()" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [""], _state} = VM.execute(proto, state) end @@ -185,9 +189,9 @@ defmodule Lua.VM.StringTest do code = "return string.char(256)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) - assert_raise Lua.VM.ArgumentError, ~r/out of range/, fn -> + assert_raise ArgumentError, ~r/out of range/, fn -> VM.execute(proto, state) end end @@ -195,10 +199,10 @@ defmodule Lua.VM.StringTest do describe "string.format" do test "string.format with %s specifier" do - code = "return string.format(\"Hello, %s!\", \"world\")" + code = ~s{return string.format("Hello, %s!", "world")} assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["Hello, world!"], _state} = VM.execute(proto, state) end @@ -206,7 +210,7 @@ defmodule Lua.VM.StringTest do code = "return string.format(\"Number: %d\", 42)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["Number: 42"], _state} = VM.execute(proto, state) end @@ -214,7 +218,7 @@ defmodule Lua.VM.StringTest do code = "return string.format(\"Float: %f\", 3.14)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [result], _state} = VM.execute(proto, state) assert result =~ "3.14" end @@ -223,7 +227,7 @@ defmodule Lua.VM.StringTest do code = "return string.format(\"Hex: %x\", 255)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["Hex: ff"], _state} = VM.execute(proto, state) end @@ -231,7 +235,7 @@ defmodule Lua.VM.StringTest do code = "return string.format(\"Hex: %X\", 255)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["Hex: FF"], _state} = VM.execute(proto, state) end @@ -239,7 +243,7 @@ defmodule Lua.VM.StringTest do code = "return string.format(\"Octal: %o\", 8)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["Octal: 10"], _state} = VM.execute(proto, state) end @@ -247,15 +251,15 @@ defmodule Lua.VM.StringTest do code = "return string.format(\"Char: %c\", 65)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["Char: A"], _state} = VM.execute(proto, state) end test "string.format with %q specifier" do - code = "return string.format(\"Quoted: %q\", \"hello\\nworld\")" + code = ~s{return string.format("Quoted: %q", "hello\\nworld")} assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [result], _state} = VM.execute(proto, state) assert result == "Quoted: \"hello\\nworld\"" end @@ -264,15 +268,15 @@ defmodule Lua.VM.StringTest do code = "return string.format(\"100%% done\")" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["100% done"], _state} = VM.execute(proto, state) end test "string.format with multiple specifiers" do - code = "return string.format(\"%s: %d (%x)\", \"Value\", 255, 255)" + code = ~s{return string.format("%s: %d (%x)", "Value", 255, 255)} assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["Value: 255 (ff)"], _state} = VM.execute(proto, state) end end @@ -286,7 +290,7 @@ defmodule Lua.VM.StringTest do assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, ["HELLO"], _state} = VM.execute(proto, state) end end @@ -297,7 +301,7 @@ defmodule Lua.VM.StringTest do code = "return string.lower(\"#{escape_string(str)}\")" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [result], _state} = VM.execute(proto, state) assert is_binary(result) assert result == String.downcase(str) @@ -309,7 +313,7 @@ defmodule Lua.VM.StringTest do code = "return string.upper(\"#{escape_string(str)}\")" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [result], _state} = VM.execute(proto, state) assert is_binary(result) assert result == String.upcase(str) @@ -321,7 +325,7 @@ defmodule Lua.VM.StringTest do code = "return string.len(\"#{escape_string(str)}\")" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [result], _state} = VM.execute(proto, state) assert is_integer(result) assert result >= 0 @@ -336,7 +340,7 @@ defmodule Lua.VM.StringTest do code = "return string.reverse(string.reverse(\"#{escape_string(str)}\"))" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [result], _state} = VM.execute(proto, state) assert result == str end @@ -347,7 +351,7 @@ defmodule Lua.VM.StringTest do code = "return string.rep(\"#{escape_string(str)}\", 0)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [""], _state} = VM.execute(proto, state) end end @@ -357,7 +361,7 @@ defmodule Lua.VM.StringTest do code = "return string.rep(\"#{escape_string(str)}\", 1)" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [result], _state} = VM.execute(proto, state) assert result == str end @@ -368,7 +372,7 @@ defmodule Lua.VM.StringTest do code = "return string.char(string.byte(string.char(#{byte})))" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [result], _state} = VM.execute(proto, state) assert result == <> end @@ -380,7 +384,7 @@ defmodule Lua.VM.StringTest do code = "return string.sub(\"#{escape_string(str)}\", 1, #{len})" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [result], _state} = VM.execute(proto, state) assert result == str end @@ -391,7 +395,7 @@ defmodule Lua.VM.StringTest do code = "return string.format(\"Result: %s\", \"#{escape_string(str)}\")" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [result], _state} = VM.execute(proto, state) assert is_binary(result) assert String.starts_with?(result, "Result: ") @@ -403,7 +407,7 @@ defmodule Lua.VM.StringTest do code = "return string.format(\"Number: %d\", #{int})" assert {:ok, ast} = Parser.parse(code) assert {:ok, proto} = Compiler.compile(ast, source: "test.lua") - state = State.new() |> Lua.VM.Stdlib.install() + state = Stdlib.install(State.new()) assert {:ok, [result], _state} = VM.execute(proto, state) assert result == "Number: #{int}" end diff --git a/test/lua/vm/value_test.exs b/test/lua/vm/value_test.exs index 7b9d486..66be5ce 100644 --- a/test/lua/vm/value_test.exs +++ b/test/lua/vm/value_test.exs @@ -1,7 +1,8 @@ defmodule Lua.VM.ValueTest do use ExUnit.Case, async: true - alias Lua.VM.{State, Value} + alias Lua.VM.State + alias Lua.VM.Value defp new_state, do: State.new() diff --git a/test/lua53_suite_test.exs b/test/lua53_suite_test.exs index 5cb2876..c007f6f 100644 --- a/test/lua53_suite_test.exs +++ b/test/lua53_suite_test.exs @@ -1,5 +1,6 @@ defmodule Lua.Lua53SuiteTest do use ExUnit.Case, async: true + import Lua.TestCase @moduletag :lua53 diff --git a/test/lua_test.exs b/test/lua_test.exs index 3dd5225..e15569e 100644 --- a/test/lua_test.exs +++ b/test/lua_test.exs @@ -487,7 +487,7 @@ defmodule LuaTest do # assert chunk.ref assert {%Lua.Chunk{} = chunk, %Lua{}} = Lua.load_chunk!(Lua.new(), ~S[print("hello")]) - assert chunk.prototype != nil + assert chunk.prototype end test "invalid strings raise Lua.CompilerException" do @@ -571,6 +571,7 @@ defmodule LuaTest do # assert {[[{"a", 1}]], _lua} = Lua.eval!(lua, "return single.bar({ a = 1 })") defmodule SingleValueState do + @moduledoc false use Lua.API, scope: "single" deflua foo(value), _state do @@ -647,6 +648,7 @@ defmodule LuaTest do # (same pattern for keyword_table_with_state, map_table, map_table_with_state) defmodule TableFunctions do + @moduledoc false use Lua.API, scope: "tables" deflua keyword_table do @@ -1041,6 +1043,7 @@ defmodule LuaTest do describe "load_api/2 and load_api/3" do defmodule TestModule do + @moduledoc false use Lua.API deflua(foo(arg), do: arg) @@ -1059,14 +1062,17 @@ defmodule LuaTest do end defmodule NoFuncsScope do + @moduledoc false use Lua.API, scope: "scope" end defmodule NoFuncsGlobal do + @moduledoc false use Lua.API end defmodule WithInstall do + @moduledoc false use Lua.API @impl Lua.API @@ -1107,7 +1113,7 @@ defmodule LuaTest do lua = Lua.load_api(lua, TestModule, scope: ["scope"]) assert {["a default"], _} = Lua.eval!(lua, "return scope.test(\"a\")") - assert {["a b"], _} = Lua.eval!(lua, "return scope.test(\"a\", \"b\")") + assert {["a b"], _} = Lua.eval!(lua, ~s{return scope.test("a", "b")}) end test "if no functions are exposed, it still creates the scope", %{lua: lua} do @@ -1145,6 +1151,7 @@ defmodule LuaTest do # """) defmodule GlobalVar do + @moduledoc false use Lua.API, scope: "gv" deflua get(name), state do @@ -1168,6 +1175,7 @@ defmodule LuaTest do describe "examples" do defmodule Examples do + @moduledoc false use Lua.API deflua double(x) do @@ -1207,7 +1215,7 @@ defmodule LuaTest do end setup do - %{lua: Lua.new() |> Lua.load_api(Examples, scope: ["example"])} + %{lua: Lua.load_api(Lua.new(), Examples, scope: ["example"])} end test "can work with numbers", %{lua: lua} do diff --git a/test/support/lua_test_case.ex b/test/support/lua_test_case.ex index 9170197..da195f6 100644 --- a/test/support/lua_test_case.ex +++ b/test/support/lua_test_case.ex @@ -8,6 +8,8 @@ defmodule Lua.TestCase do use ExUnit.CaseTemplate + alias Lua.VM.RuntimeError + @doc """ Runs a .lua file, treating Lua assert() failures as ExUnit failures. @@ -60,11 +62,11 @@ defmodule Lua.TestCase do {results, state} {:error, error} -> - raise Lua.VM.RuntimeError, value: "compile error: #{inspect(error)}" + raise RuntimeError, value: "compile error: #{inspect(error)}" end {:error, error} -> - raise Lua.VM.RuntimeError, value: "parse error: #{inspect(error)}" + raise RuntimeError, value: "parse error: #{inspect(error)}" end end) @@ -97,16 +99,16 @@ defmodule Lua.TestCase do try do Lua.VM.Executor.call_function(func, [], state) - raise Lua.VM.RuntimeError, + raise RuntimeError, value: "expected error matching '#{pattern}' but no error was raised" rescue - e in [Lua.VM.RuntimeError, Lua.VM.TypeError, Lua.VM.AssertionError] -> + e in [RuntimeError, Lua.VM.TypeError, Lua.VM.AssertionError] -> error_msg = extract_error_message(e) if String.contains?(error_msg, pattern) do {[true], state} else - raise Lua.VM.RuntimeError, + raise RuntimeError, value: "expected error matching '#{pattern}' but got: #{error_msg}" end end @@ -118,8 +120,7 @@ defmodule Lua.TestCase do # Extract error message from exception defp extract_error_message(%{value: value}) when is_binary(value), do: value - defp extract_error_message(%{value: value}) when not is_nil(value), - do: Lua.VM.Value.to_string(value) + defp extract_error_message(%{value: value}) when not is_nil(value), do: Lua.VM.Value.to_string(value) defp extract_error_message(e), do: Exception.message(e) end From fec3441bcbcddf05603da64ea5e2545953dbde2a Mon Sep 17 00:00:00 2001 From: Dave Lucia Date: Wed, 11 Feb 2026 04:57:25 -0800 Subject: [PATCH 2/2] format: Apply styler formatting --- lib/lua/compiler/codegen.ex | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/lua/compiler/codegen.ex b/lib/lua/compiler/codegen.ex index a61b405..4d0877b 100644 --- a/lib/lua/compiler/codegen.ex +++ b/lib/lua/compiler/codegen.ex @@ -147,8 +147,7 @@ defmodule Lua.Compiler.Codegen do vararg_instruction = Instruction.vararg(vararg_base, 0) # Return with -1 to indicate variable number of results - {init_instructions ++ [vararg_instruction, Instruction.return_instr(base_reg, -1)], - ctx} + {init_instructions ++ [vararg_instruction, Instruction.return_instr(base_reg, -1)], ctx} _ -> # Normal multi-value return