Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --emit-lua-preserve-columns flag #572

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 34 additions & 4 deletions spec/translator_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@
local util = require "pallene.util"
local execution_tests = require "spec.execution_tests"

local function compile(filename, pallene_code)
local function compile(filename, pallene_code, preserve_columns)
assert(util.set_file_contents(filename, pallene_code))
local cmd = string.format("pallenec %s --emit-lua", util.shell_quote(filename))
local flag = "--emit-lua"
if preserve_columns then
flag = "--emit-lua-preserve-columns"
end
local cmd = string.format("pallenec %s " .. flag, util.shell_quote(filename))
local ok, _, _, error_message = util.outputs_of_execute(cmd)
return ok, error_message
end
Expand All @@ -32,8 +36,8 @@ end)
-- Translation tests
--------------------

local function assert_translation(pallene_code, expected)
assert(compile("__translation_test__.pln", pallene_code))
local function assert_translation(pallene_code, expected, preserve_columns)
assert(compile("__translation_test__.pln", pallene_code, preserve_columns))
local contents = assert(util.get_file_contents("__translation_test__.lua"))
-- The introduction of math.ln in Pallene to workaround single param math.log requires emitted
-- Lua code to handle this as well. The current workaround injects "math.ln = math.log; " at
Expand Down Expand Up @@ -483,6 +487,7 @@ local m: module = {}
local xs: {any} = {10, "hello", 3.14}

local function f(x: any, y: any): any
return nil as nil
end

return m
Expand All @@ -492,12 +497,37 @@ local m = {}
local xs = {10, "hello", 3.14}

local function f(x, y)
return nil
end

return m
]])
end)

it("Remove any type annotation (preserving columns)", function ()
assert_translation(
[[
local m: module = {}
local xs: {any} = {10, "hello", 3.14}

local function f(x: any, y: any): any
return nil as nil
end

return m
]],
[[
local m = {}
local xs = {10, "hello", 3.14}

local function f(x , y ) ]] .. "\n" .. [[
return nil ]] .. "\n" .. [[
end

return m
]], true)
end)

it("Remove function shapes", function ()
assert_translation(
[[
Expand Down
20 changes: 17 additions & 3 deletions src/pallene/driver.lua
Original file line number Diff line number Diff line change
Expand Up @@ -149,17 +149,31 @@ end
local function compile_pln_to_lua(input_ext, output_ext, input_file_name, base_name)
assert(input_ext == "pln")

local preserve_columns = false
if output_ext == "lua_pc" then
preserve_columns = true
output_ext = "lua"
end

local input, err = driver.load_input(input_file_name)
if not input then
return false, { err }
end

local prog_ast, errs = driver.compile_internal(input_file_name, input, "checker")
-- Perform compilation steps up to (including) variable verifications.
local prog_ast, errs = driver.compile_internal(input_file_name, input, "uninitialized")
if not prog_ast then
return false, errs
end

-- Redo the compilation, this time stopping after the syntax checker to have
-- an AST that we can translate to lua.
prog_ast, errs = driver.compile_internal(input_file_name, input, "checker")
if not prog_ast then
return false, errs
end

local translation = translator.translate(input, prog_ast)
local translation = translator.translate(input, prog_ast, preserve_columns)

assert(util.set_file_contents(base_name .. "." .. output_ext, translation))
return true, {}
Expand All @@ -180,7 +194,7 @@ function driver.compile(argv0, opt_level, input_ext, output_ext, input_file_name

local mod_name = string.gsub(output_base_name, "/", "_")

if output_ext == "lua" then
if output_ext == "lua" or output_ext == "lua_pc" then
return compile_pln_to_lua(input_ext, output_ext, input_file_name, output_base_name)
else
local first_step = step_index[input_ext] or error("invalid extension")
Expand Down
7 changes: 6 additions & 1 deletion src/pallene/pallenec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ do
p:mutex(
p:flag("--emit-c", "Generate a .c file instead of an executable"),
p:flag("--emit-lua", "Generate a .lua file instead of an executable"),
p:flag("--emit-lua-preserve-columns",
"Generate a .lua file instead of an executable with"
.. "\nthe positions of tokens preserved (useful with"
.. "\nLua diagnostics tool source mapping)"),
p:flag("--compile-c", "Compile a .c file generated by --emit-c"),
p:flag("--only-check","Check for syntax or type errors, without compiling"),
p:flag("--print-ir", "Show the intermediate representation for a program")
Expand Down Expand Up @@ -60,7 +64,7 @@ local function compile_up_to(stop_after)
end

local function do_check()
compile_up_to("checker")
compile_up_to("uninitialized")
end

local function do_print_ir()
Expand All @@ -71,6 +75,7 @@ end
function pallenec.main()
if opts.emit_c then compile("pln", "c")
elseif opts.emit_lua then compile("pln", "lua")
elseif opts.emit_lua_preserve_columns then compile("pln", "lua_pc")
elseif opts.compile_c then compile("c" , "so")
elseif opts.only_check then do_check()
elseif opts.print_ir then do_print_ir()
Expand Down
13 changes: 9 additions & 4 deletions src/pallene/translator.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,13 @@ local translator = {}

local Translator = util.Class()

function Translator:init(input)
function Translator:init(input, preserve_columns)
self.input = input -- string
if preserve_columns then
self.eraser = " " -- insert a space for each removed character
else
self.eraser = "" -- insert nothing when removing characters
end
self.last_index = 1 -- integer
self.partials = {} -- list of strings
return self
Expand All @@ -51,7 +56,7 @@ function Translator:erase_region(start_index, stop_index)
self:add_previous(start_index - 1)

local region = self.input:sub(start_index, stop_index)
local partial = region:gsub("[^\n\r]", "")
local partial = region:gsub("[^\n\r]", self.eraser)
table.insert(self.partials, partial)

self.last_index = stop_index + 1
Expand All @@ -65,8 +70,8 @@ function Translator:prepend_compatibility_code()
self.partials[1] = "math.ln = math.log; " .. self.partials[1]
end

function translator.translate(input, prog_ast)
local instance = Translator.new(input)
function translator.translate(input, prog_ast, preserve_columns)
local instance = Translator.new(input, preserve_columns)

-- Erase all type regions, while preserving comments
-- As a sanity check, assert that the comment regions are either inside or outside the type
Expand Down