use crate::common;
use common::e2e_helpers::create_runtime_with_search;
use pasta_dsl::parser::parse_str;
use pasta_lua::LuaTranspiler;
use pasta_lua::context::TranspileContext;
fn transpile_with_context(source: &str) -> (String, TranspileContext) {
let file = parse_str(source, "test.pasta").expect("Failed to parse");
let transpiler = LuaTranspiler::default();
let mut output = Vec::new();
let ctx = transpiler
.transpile(&file, &mut output)
.expect("Failed to transpile");
let lua_code = String::from_utf8(output).expect("Invalid UTF-8");
(lua_code, ctx)
}
#[test]
fn test_dynamic_call_resolves_scene() {
let source = r#"
*テスト
$target=「サブ」
>$target
・サブ
さくら:「サブです」
"#;
let (lua_code, ctx) = transpile_with_context(source);
let lua = create_runtime_with_search(ctx).unwrap();
lua.load(&lua_code).exec().unwrap();
assert!(
lua_code.contains("tostring(var.target)"),
"Dynamic call should use tostring(var.target). Code:\n{lua_code}"
);
}
#[test]
fn test_dynamic_call_code_gen_output() {
let source = r#"
*メイン
$target=「挨拶」
>$target
"#;
let (lua_code, _ctx) = transpile_with_context(source);
assert!(
lua_code.contains(r#"var.target = "挨拶""#),
"Variable assignment not found. Code:\n{lua_code}"
);
assert!(
lua_code.contains("tostring(var.target)"),
"Dynamic call tostring not found. Code:\n{lua_code}"
);
assert!(
lua_code.contains("act:call(SCENE.__global_name__, tostring(var.target)"),
"Dynamic call format incorrect. Code:\n{lua_code}"
);
}
#[test]
fn test_dynamic_call_no_match_returns_nil() {
let source = r#"
*メイン
$target=「存在しないシーン」
>$target
"#;
let (lua_code, ctx) = transpile_with_context(source);
let lua = create_runtime_with_search(ctx).unwrap();
lua.load(&lua_code).exec().unwrap();
lua.load("require('pasta').finalize_scene()").exec().unwrap();
let result: mlua::Value = lua
.load(
r#"
local PASTA = require "pasta"
local SCENE = require "pasta.scene"
local ACT = require "pasta.act"
-- Look up the メイン scene
local result = SCENE.search("メイン", nil)
if result == nil then
return "scene_not_found"
end
return "scene_exists"
"#,
)
.eval()
.unwrap();
let result_str = result.as_string().unwrap().to_str().unwrap().to_string();
assert_eq!(result_str, "scene_exists");
}
#[test]
fn test_nil_guard_in_act_call() {
let ctx = TranspileContext::new();
let lua = create_runtime_with_search(ctx).unwrap();
let result: mlua::Value = lua
.load(
r#"
local ACT = require "pasta.act"
-- Create a minimal act object
local act = ACT.new({}, {})
-- Call with nil key — should return nil and not crash
local result = act:call("test_scene", nil, {})
if result == nil then
return "nil_returned"
else
return "unexpected: " .. tostring(result)
end
"#,
)
.eval()
.unwrap();
let result_str = result.as_string().unwrap().to_str().unwrap().to_string();
assert_eq!(
result_str, "nil_returned",
"act:call with nil key should return nil (nil guard)"
);
}
#[test]
fn test_static_call_lua_output_unchanged() {
let source = r#"
*メイン
>サブシーン
"#;
let (lua_code, _ctx) = transpile_with_context(source);
assert!(
lua_code.contains(r#"act:call(SCENE.__global_name__, "サブシーン""#),
"Static call format should use quoted string. Code:\n{lua_code}"
);
assert!(
!lua_code.contains("tostring("),
"Static call should not use tostring(). Code:\n{lua_code}"
);
}
#[test]
fn test_dynamic_call_global_var_code_gen() {
let source = r#"
*メイン
>$*global_target
"#;
let (lua_code, _ctx) = transpile_with_context(source);
assert!(
lua_code.contains("tostring(save.global_target)"),
"Global var dynamic call should use save.xxx. Code:\n{lua_code}"
);
}