JIT host-bridge: add console.warn/error and LowerCore map get/has/set lowering; extern console methods arity widened
This commit is contained in:
@ -223,6 +223,9 @@ impl JitEngine {
|
||||
self.register_extern(hb::SYM_HOST_MAP_GET, Arc::new(|args| hb::map_get(args)));
|
||||
self.register_extern(hb::SYM_HOST_MAP_SET, Arc::new(|args| hb::map_set(args)));
|
||||
self.register_extern(hb::SYM_HOST_MAP_HAS, Arc::new(|args| hb::map_has(args)));
|
||||
self.register_extern(hb::SYM_HOST_CONSOLE_LOG, Arc::new(|args| hb::console_log(args)));
|
||||
self.register_extern(hb::SYM_HOST_CONSOLE_WARN, Arc::new(|args| hb::console_warn(args)));
|
||||
self.register_extern(hb::SYM_HOST_CONSOLE_ERROR, Arc::new(|args| hb::console_error(args)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
20
src/jit/extern/host_bridge.rs
vendored
20
src/jit/extern/host_bridge.rs
vendored
@ -58,6 +58,9 @@ pub const SYM_HOST_MAP_GET: &str = "nyash.host.map.get"; // (MapBox, key)
|
||||
pub const SYM_HOST_MAP_SET: &str = "nyash.host.map.set"; // (MapBox, key, val)
|
||||
pub const SYM_HOST_MAP_SIZE: &str = "nyash.host.map.size"; // (MapBox)
|
||||
pub const SYM_HOST_MAP_HAS: &str = "nyash.host.map.has"; // (MapBox, key)
|
||||
pub const SYM_HOST_CONSOLE_LOG: &str = "nyash.host.console.log"; // (value)
|
||||
pub const SYM_HOST_CONSOLE_WARN: &str = "nyash.host.console.warn"; // (value)
|
||||
pub const SYM_HOST_CONSOLE_ERROR: &str = "nyash.host.console.error"; // (value)
|
||||
|
||||
pub fn array_get(args: &[VMValue]) -> VMValue {
|
||||
if let Some(h) = to_handle(args.get(0).unwrap_or(&VMValue::Void)) { call_slot(h, 100, &args[1..]) } else { VMValue::Void }
|
||||
@ -81,3 +84,20 @@ pub fn map_has(args: &[VMValue]) -> VMValue {
|
||||
if let Some(h) = to_handle(args.get(0).unwrap_or(&VMValue::Void)) { call_slot(h, 202, &args[1..]) } else { VMValue::Bool(false) }
|
||||
}
|
||||
|
||||
pub fn console_log(args: &[VMValue]) -> VMValue {
|
||||
// JIT host-bridge簡易版: 最初の引数を文字列化してstdoutへ
|
||||
if let Some(a0) = args.get(0) {
|
||||
println!("{}", a0.to_string());
|
||||
}
|
||||
VMValue::Void
|
||||
}
|
||||
|
||||
pub fn console_warn(args: &[VMValue]) -> VMValue {
|
||||
if let Some(a0) = args.get(0) { eprintln!("[warn] {}", a0.to_string()); }
|
||||
VMValue::Void
|
||||
}
|
||||
|
||||
pub fn console_error(args: &[VMValue]) -> VMValue {
|
||||
if let Some(a0) = args.get(0) { eprintln!("[error] {}", a0.to_string()); }
|
||||
VMValue::Void
|
||||
}
|
||||
|
||||
@ -63,8 +63,14 @@ impl LowerCore {
|
||||
args: &Vec<ValueId>,
|
||||
_func: &MirFunction,
|
||||
) -> Result<(), String> {
|
||||
// env.console.log/println → ConsoleBox に委譲
|
||||
// env.console.log/println → ConsoleBox に委譲(host-bridge有効時は直接ログ)
|
||||
if iface_name == "env.console" && (method_name == "log" || method_name == "println") {
|
||||
if std::env::var("NYASH_JIT_HOST_BRIDGE").ok().as_deref() == Some("1") {
|
||||
// a0: 先頭引数を最小限で積む
|
||||
if let Some(arg0) = args.get(0) { self.push_value_if_known_or_param(b, arg0); } else { b.emit_const_i64(0); }
|
||||
b.emit_host_call(crate::jit::r#extern::host_bridge::SYM_HOST_CONSOLE_LOG, 1, false);
|
||||
return Ok(());
|
||||
}
|
||||
// Ensure we have a Console handle (hostcall birth shim)
|
||||
b.emit_host_call("nyash.console.birth_h", 0, true);
|
||||
// a1: first argument best-effort
|
||||
|
||||
@ -28,6 +28,71 @@ pub fn lower_array_get(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lower_map_size(
|
||||
b: &mut dyn IRBuilder,
|
||||
param_index: &HashMap<ValueId, usize>,
|
||||
recv: &ValueId,
|
||||
dst_is_some: bool,
|
||||
) {
|
||||
let use_bridge = std::env::var("NYASH_JIT_HOST_BRIDGE").ok().as_deref() == Some("1");
|
||||
if let Some(pidx) = param_index.get(recv).copied() {
|
||||
b.emit_param_i64(pidx);
|
||||
let sym = if use_bridge { crate::jit::r#extern::host_bridge::SYM_HOST_MAP_SIZE } else { crate::jit::r#extern::collections::SYM_MAP_SIZE_H };
|
||||
b.emit_host_call(sym, 1, dst_is_some);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lower_map_get(
|
||||
b: &mut dyn IRBuilder,
|
||||
param_index: &HashMap<ValueId, usize>,
|
||||
known_i64: &HashMap<ValueId, i64>,
|
||||
recv: &ValueId,
|
||||
key: &ValueId,
|
||||
dst_is_some: bool,
|
||||
) {
|
||||
let use_bridge = std::env::var("NYASH_JIT_HOST_BRIDGE").ok().as_deref() == Some("1");
|
||||
if let Some(pidx) = param_index.get(recv).copied() {
|
||||
b.emit_param_i64(pidx);
|
||||
if let Some(i) = known_i64.get(key).copied() { b.emit_const_i64(i); } else if let Some(kp) = param_index.get(key).copied() { b.emit_param_i64(kp); } else { b.emit_const_i64(0); }
|
||||
let sym = if use_bridge { crate::jit::r#extern::host_bridge::SYM_HOST_MAP_GET } else { crate::jit::r#extern::collections::SYM_MAP_GET_H };
|
||||
b.emit_host_call(sym, 2, dst_is_some);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lower_map_has(
|
||||
b: &mut dyn IRBuilder,
|
||||
param_index: &HashMap<ValueId, usize>,
|
||||
known_i64: &HashMap<ValueId, i64>,
|
||||
recv: &ValueId,
|
||||
key: &ValueId,
|
||||
dst_is_some: bool,
|
||||
) {
|
||||
let use_bridge = std::env::var("NYASH_JIT_HOST_BRIDGE").ok().as_deref() == Some("1");
|
||||
if let Some(pidx) = param_index.get(recv).copied() {
|
||||
b.emit_param_i64(pidx);
|
||||
if let Some(i) = known_i64.get(key).copied() { b.emit_const_i64(i); } else if let Some(kp) = param_index.get(key).copied() { b.emit_param_i64(kp); } else { b.emit_const_i64(0); }
|
||||
let sym = if use_bridge { crate::jit::r#extern::host_bridge::SYM_HOST_MAP_HAS } else { crate::jit::r#extern::collections::SYM_MAP_HAS_H };
|
||||
b.emit_host_call(sym, 2, dst_is_some);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lower_map_set(
|
||||
b: &mut dyn IRBuilder,
|
||||
param_index: &HashMap<ValueId, usize>,
|
||||
known_i64: &HashMap<ValueId, i64>,
|
||||
recv: &ValueId,
|
||||
key: &ValueId,
|
||||
value: &ValueId,
|
||||
) {
|
||||
let use_bridge = std::env::var("NYASH_JIT_HOST_BRIDGE").ok().as_deref() == Some("1");
|
||||
if let Some(pidx) = param_index.get(recv).copied() {
|
||||
b.emit_param_i64(pidx);
|
||||
if let Some(i) = known_i64.get(key).copied() { b.emit_const_i64(i); } else if let Some(kp) = param_index.get(key).copied() { b.emit_param_i64(kp); } else { b.emit_const_i64(0); }
|
||||
if let Some(i) = known_i64.get(value).copied() { b.emit_const_i64(i); } else if let Some(vp) = param_index.get(value).copied() { b.emit_param_i64(vp); } else { b.emit_const_i64(0); }
|
||||
let sym = if use_bridge { crate::jit::r#extern::host_bridge::SYM_HOST_MAP_SET } else { crate::jit::r#extern::collections::SYM_MAP_SET_H };
|
||||
b.emit_host_call(sym, 3, false);
|
||||
}
|
||||
}
|
||||
pub fn lower_array_set(
|
||||
b: &mut dyn IRBuilder,
|
||||
param_index: &HashMap<ValueId, usize>,
|
||||
@ -192,26 +257,10 @@ pub fn lower_box_call(
|
||||
}
|
||||
}
|
||||
// Map
|
||||
"size" => {
|
||||
crate::jit::events::emit_lower(
|
||||
serde_json::json!({"id": crate::jit::r#extern::collections::SYM_MAP_SIZE_H, "decision":"allow", "reason":"sig_ok", "argc":1, "arg_types":["Handle"]}),
|
||||
"hostcall","<jit>"
|
||||
);
|
||||
if let Some(pidx) = param_index.get(recv).copied() {
|
||||
b.emit_param_i64(pidx);
|
||||
let sym = if std::env::var("NYASH_JIT_HOST_BRIDGE").ok().as_deref() == Some("1") { crate::jit::r#extern::host_bridge::SYM_HOST_MAP_SIZE } else { crate::jit::r#extern::collections::SYM_MAP_SIZE_H };
|
||||
b.emit_host_call(sym, 1, dst.is_some());
|
||||
} else {
|
||||
// fallback: id-only (receiver not param)
|
||||
crate::jit::events::emit_lower(
|
||||
serde_json::json!({"id": crate::jit::r#extern::collections::SYM_MAP_SIZE, "decision":"fallback", "reason":"receiver_not_param", "argc":1, "arg_types":["I64"]}),
|
||||
"hostcall","<jit>"
|
||||
);
|
||||
b.emit_const_i64(-1);
|
||||
b.emit_host_call(crate::jit::r#extern::collections::SYM_MAP_SIZE, 1, dst.is_some());
|
||||
}
|
||||
}
|
||||
// get/has/set: keep generic path for now (no special lowering here)
|
||||
"size" => { lower_map_size(b, param_index, recv, dst.is_some()); }
|
||||
"get" => { if let Some(k) = args.get(0) { lower_map_get(b, param_index, known_i64, recv, k, dst.is_some()); } }
|
||||
"has" => { if let Some(k) = args.get(0) { lower_map_has(b, param_index, known_i64, recv, k, dst.is_some()); } }
|
||||
"set" => { if args.len() >= 2 { lower_map_set(b, param_index, known_i64, recv, &args[0], &args[1]); } }
|
||||
"has" => {
|
||||
// Decide on key kind via registry and known values
|
||||
use crate::jit::hostcall_registry::{check_signature, ArgKind};
|
||||
|
||||
@ -15,7 +15,9 @@ pub struct ExternSpec {
|
||||
|
||||
static EXTERNS: Lazy<Vec<ExternSpec>> = Lazy::new(|| vec![
|
||||
// console
|
||||
ExternSpec { iface: "env.console", method: "log", min_arity: 1, max_arity: 1, slot: Some(10) },
|
||||
ExternSpec { iface: "env.console", method: "log", min_arity: 1, max_arity: 255, slot: Some(10) },
|
||||
ExternSpec { iface: "env.console", method: "warn", min_arity: 1, max_arity: 255, slot: Some(10) },
|
||||
ExternSpec { iface: "env.console", method: "error", min_arity: 1, max_arity: 255, slot: Some(10) },
|
||||
// debug
|
||||
ExternSpec { iface: "env.debug", method: "trace", min_arity: 1, max_arity: 255, slot: Some(11) },
|
||||
// runtime
|
||||
|
||||
Reference in New Issue
Block a user