restore(lang/compiler): bring back lang/src/compiler from e917d400; add Hako index canaries and docs; implement Rust-side index operator (Array/Map get/set) with Fail‑Fast diagnostics
- restore: lang/src/compiler/** (parser/emit/builder/pipeline_v2) from e917d400 - docs: docs/development/selfhosting/index-operator-hako.md - smokes(hako): tools/smokes/v2/profiles/quick/core/index_operator_hako.sh (opt-in) - smokes(vm): adjust index_operator_vm.sh for semicolon gate + stable error text - rust/parser: allow IndexExpr and assignment LHS=Index; postfix parse LBRACK chain - rust/builder: lower arr/map index to BoxCall get/set; annotate array/map literals; Fail‑Fast for unsupported types - CURRENT_TASK: mark Rust side done; add Hako tasks checklist Note: files disappeared likely due to branch FF to a lineage without lang/src/compiler; no explicit delete commit found. Added anchor checks and suggested CI guard in follow-up.
This commit is contained in:
@ -66,6 +66,8 @@ impl super::MirBuilder {
|
||||
let stmt = AssignStmt::try_from(node).expect("ASTNode::Assignment must convert");
|
||||
if let ASTNode::FieldAccess { object, field, .. } = stmt.target.as_ref() {
|
||||
self.build_field_assignment(*object.clone(), field.clone(), *stmt.value.clone())
|
||||
} else if let ASTNode::Index { target, index, .. } = stmt.target.as_ref() {
|
||||
self.build_index_assignment(*target.clone(), *index.clone(), *stmt.value.clone())
|
||||
} else if let ASTNode::Variable { name, .. } = stmt.target.as_ref() {
|
||||
self.build_assignment(name.clone(), *stmt.value.clone())
|
||||
} else {
|
||||
@ -73,6 +75,10 @@ impl super::MirBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
ASTNode::Index { target, index, .. } => {
|
||||
self.build_index_expression(*target.clone(), *index.clone())
|
||||
}
|
||||
|
||||
node @ ASTNode::FunctionCall { .. } => {
|
||||
let c = CallExpr::try_from(node).expect("ASTNode::FunctionCall must convert");
|
||||
self.build_function_call(c.name, c.arguments)
|
||||
@ -213,6 +219,11 @@ impl super::MirBuilder {
|
||||
box_type: "ArrayBox".to_string(),
|
||||
args: vec![],
|
||||
})?;
|
||||
self.value_origin_newbox
|
||||
.insert(arr_id, "ArrayBox".to_string());
|
||||
self
|
||||
.value_types
|
||||
.insert(arr_id, super::MirType::Box("ArrayBox".to_string()));
|
||||
for e in elements {
|
||||
let v = self.build_expression_impl(e)?;
|
||||
self.emit_instruction(MirInstruction::BoxCall {
|
||||
@ -233,6 +244,12 @@ impl super::MirBuilder {
|
||||
box_type: "MapBox".to_string(),
|
||||
args: vec![],
|
||||
})?;
|
||||
self
|
||||
.value_origin_newbox
|
||||
.insert(map_id, "MapBox".to_string());
|
||||
self
|
||||
.value_types
|
||||
.insert(map_id, super::MirType::Box("MapBox".to_string()));
|
||||
for (k, expr) in entries {
|
||||
// const string key
|
||||
let k_id = crate::mir::builder::emission::constant::emit_string(self, k);
|
||||
@ -310,4 +327,110 @@ impl super::MirBuilder {
|
||||
_ => Err(format!("Unsupported AST node type: {:?}", ast)),
|
||||
}
|
||||
}
|
||||
|
||||
fn infer_index_target_class(&self, target_val: ValueId) -> Option<String> {
|
||||
if let Some(cls) = self.value_origin_newbox.get(&target_val) {
|
||||
return Some(cls.clone());
|
||||
}
|
||||
self.value_types.get(&target_val).and_then(|ty| match ty {
|
||||
super::MirType::Box(name) => Some(name.clone()),
|
||||
super::MirType::String => Some("String".to_string()),
|
||||
super::MirType::Integer => Some("Integer".to_string()),
|
||||
super::MirType::Float => Some("Float".to_string()),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
fn format_index_target_kind(class_hint: Option<&String>) -> String {
|
||||
class_hint
|
||||
.map(|s| s.as_str())
|
||||
.filter(|s| !s.is_empty())
|
||||
.unwrap_or("unknown")
|
||||
.to_string()
|
||||
}
|
||||
|
||||
pub(super) fn build_index_expression(
|
||||
&mut self,
|
||||
target: ASTNode,
|
||||
index: ASTNode,
|
||||
) -> Result<ValueId, String> {
|
||||
let target_val = self.build_expression(target)?;
|
||||
let class_hint = self.infer_index_target_class(target_val);
|
||||
|
||||
match class_hint.as_deref() {
|
||||
Some("ArrayBox") => {
|
||||
let index_val = self.build_expression(index)?;
|
||||
let dst = self.value_gen.next();
|
||||
self.emit_box_or_plugin_call(
|
||||
Some(dst),
|
||||
target_val,
|
||||
"get".to_string(),
|
||||
None,
|
||||
vec![index_val],
|
||||
super::EffectMask::READ,
|
||||
)?;
|
||||
Ok(dst)
|
||||
}
|
||||
Some("MapBox") => {
|
||||
let index_val = self.build_expression(index)?;
|
||||
let dst = self.value_gen.next();
|
||||
self.emit_box_or_plugin_call(
|
||||
Some(dst),
|
||||
target_val,
|
||||
"get".to_string(),
|
||||
None,
|
||||
vec![index_val],
|
||||
super::EffectMask::READ,
|
||||
)?;
|
||||
Ok(dst)
|
||||
}
|
||||
_ => Err(format!(
|
||||
"index operator is only supported for Array/Map (found {})",
|
||||
Self::format_index_target_kind(class_hint.as_ref())
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn build_index_assignment(
|
||||
&mut self,
|
||||
target: ASTNode,
|
||||
index: ASTNode,
|
||||
value: ASTNode,
|
||||
) -> Result<ValueId, String> {
|
||||
let target_val = self.build_expression(target)?;
|
||||
let class_hint = self.infer_index_target_class(target_val);
|
||||
|
||||
match class_hint.as_deref() {
|
||||
Some("ArrayBox") => {
|
||||
let index_val = self.build_expression(index)?;
|
||||
let value_val = self.build_expression(value)?;
|
||||
self.emit_box_or_plugin_call(
|
||||
None,
|
||||
target_val,
|
||||
"set".to_string(),
|
||||
None,
|
||||
vec![index_val, value_val],
|
||||
super::EffectMask::MUT,
|
||||
)?;
|
||||
Ok(value_val)
|
||||
}
|
||||
Some("MapBox") => {
|
||||
let index_val = self.build_expression(index)?;
|
||||
let value_val = self.build_expression(value)?;
|
||||
self.emit_box_or_plugin_call(
|
||||
None,
|
||||
target_val,
|
||||
"set".to_string(),
|
||||
None,
|
||||
vec![index_val, value_val],
|
||||
super::EffectMask::MUT,
|
||||
)?;
|
||||
Ok(value_val)
|
||||
}
|
||||
_ => Err(format!(
|
||||
"index assignment is only supported for Array/Map (found {})",
|
||||
Self::format_index_target_kind(class_hint.as_ref())
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user