Skip to content

Commit ea44729

Browse files
committed
feat: extend GrammarInterpreter with complete declaration support
- Add helper methods for parameter lists, interned string lists, and variant lists - Add TypedParameter, TypedVariant, TypedVariantFields conversion from ParsedValue - Add Variable, TypeAlias, Import, and Enum declaration types to construct_declaration - Export TypedVariantFields and TypedTypeAlias from typed_ast lib - Add Parameter and Variant variants to ParsedValue enum
1 parent 0658528 commit ea44729

3 files changed

Lines changed: 282 additions & 2 deletions

File tree

crates/typed_ast/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ pub use typed_ast::{
141141
// Defer type
142142
TypedDefer,
143143
// Class/Struct/Enum types
144-
TypedClass, TypedEnum, TypedField, TypedVariant, TypedTypeParam,
144+
TypedClass, TypedEnum, TypedField, TypedVariant, TypedVariantFields, TypedTypeParam, TypedTypeAlias,
145145
// Import types
146146
TypedImport, TypedImportItem, TypedModule,
147147
// Extern types for external declarations

crates/zyn_peg/src/runtime2/interpreter.rs

Lines changed: 277 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use zyntax_typed_ast::{
1717
TypedDeclaration, TypedFunction, TypedLet, TypedCall, TypedProgram,
1818
TypedIf, TypedWhile, TypedFor, TypedUnary, TypedFieldAccess, TypedIndex,
1919
TypedRange, TypedStructLiteral, TypedFieldInit, TypedPattern,
20+
TypedParameter, TypedVariant, TypedVariantFields, TypedTypeAlias, ParameterKind,
2021
UnaryOp,
2122
typed_node, Span,
2223
type_registry::{Type, PrimitiveType, Mutability, Visibility, CallingConvention},
@@ -505,7 +506,7 @@ impl<'g> GrammarInterpreter<'g> {
505506
let decl = match variant {
506507
"Function" => {
507508
let name = self.get_field_as_interned("name", fields, state)?;
508-
let params = vec![]; // TODO: parse params from fields
509+
let params = self.get_field_as_param_list("params", fields, state)?;
509510
let return_type = self.get_field_optional("return_type", fields, state)?
510511
.unwrap_or(Type::Primitive(PrimitiveType::Unit));
511512
let body = self.get_field_optional_block("body", fields, state)?;
@@ -523,6 +524,55 @@ impl<'g> GrammarInterpreter<'g> {
523524
link_name: None,
524525
})
525526
}
527+
"Variable" => {
528+
let name = self.get_field_as_interned("name", fields, state)?;
529+
let ty = self.get_field_optional("type_annotation", fields, state)?
530+
.unwrap_or(Type::Any);
531+
let initializer = self.get_field_optional_expr("initializer", fields, state)?;
532+
let is_mutable = self.get_field_as_bool("is_mutable", fields, state).unwrap_or(false);
533+
534+
TypedDeclaration::Variable(zyntax_typed_ast::TypedVariable {
535+
name,
536+
ty,
537+
mutability: if is_mutable { Mutability::Mutable } else { Mutability::Immutable },
538+
initializer: initializer.map(Box::new),
539+
visibility: Visibility::Public,
540+
})
541+
}
542+
"TypeAlias" => {
543+
let name = self.get_field_as_interned("name", fields, state)?;
544+
let target = self.get_field_optional("target", fields, state)?
545+
.unwrap_or(Type::Any);
546+
547+
TypedDeclaration::TypeAlias(TypedTypeAlias {
548+
name,
549+
type_params: vec![],
550+
target,
551+
visibility: Visibility::Public,
552+
span,
553+
})
554+
}
555+
"Import" => {
556+
let module_path = self.get_field_as_interned_list("path", fields, state)?;
557+
558+
TypedDeclaration::Import(zyntax_typed_ast::TypedImport {
559+
module_path,
560+
items: vec![zyntax_typed_ast::TypedImportItem::Glob],
561+
span,
562+
})
563+
}
564+
"Enum" => {
565+
let name = self.get_field_as_interned("name", fields, state)?;
566+
let variants = self.get_field_as_variant_list("variants", fields, state)?;
567+
568+
TypedDeclaration::Enum(zyntax_typed_ast::TypedEnum {
569+
name,
570+
type_params: vec![],
571+
variants,
572+
visibility: Visibility::Public,
573+
span,
574+
})
575+
}
526576
_ => return Err(format!("unknown TypedDeclaration variant: {}", variant)),
527577
};
528578

@@ -1098,6 +1148,232 @@ impl<'g> GrammarInterpreter<'g> {
10981148
}
10991149
}
11001150

1151+
/// Get a field as a list of function parameters
1152+
fn get_field_as_param_list<'a>(
1153+
&self,
1154+
name: &str,
1155+
fields: &[(String, ExprIR)],
1156+
state: &mut ParserState<'a>,
1157+
) -> Result<Vec<TypedParameter>, String> {
1158+
match self.get_field(name, fields) {
1159+
Some(expr) => {
1160+
let val = self.eval_expr(expr, state)?;
1161+
match val {
1162+
ParsedValue::List(items) => {
1163+
let mut result = Vec::new();
1164+
for item in items {
1165+
let param = self.parsed_value_to_param(item, state)?;
1166+
result.push(param);
1167+
}
1168+
Ok(result)
1169+
}
1170+
ParsedValue::None => Ok(vec![]),
1171+
ParsedValue::Optional(None) => Ok(vec![]),
1172+
ParsedValue::Optional(Some(inner)) => {
1173+
match *inner {
1174+
ParsedValue::List(items) => {
1175+
let mut result = Vec::new();
1176+
for item in items {
1177+
let param = self.parsed_value_to_param(item, state)?;
1178+
result.push(param);
1179+
}
1180+
Ok(result)
1181+
}
1182+
other => {
1183+
let param = self.parsed_value_to_param(other, state)?;
1184+
Ok(vec![param])
1185+
}
1186+
}
1187+
}
1188+
ParsedValue::Parameter(p) => Ok(vec![p]),
1189+
other => {
1190+
// Single item - try to convert
1191+
let param = self.parsed_value_to_param(other, state)?;
1192+
Ok(vec![param])
1193+
}
1194+
}
1195+
}
1196+
None => Ok(vec![]),
1197+
}
1198+
}
1199+
1200+
/// Convert ParsedValue to TypedParameter
1201+
fn parsed_value_to_param<'a>(
1202+
&self,
1203+
val: ParsedValue,
1204+
state: &mut ParserState<'a>,
1205+
) -> Result<TypedParameter, String> {
1206+
match val {
1207+
ParsedValue::Parameter(p) => Ok(p),
1208+
ParsedValue::FieldInit { name, value } => {
1209+
// Convert FieldInit to a parameter (name: Type format)
1210+
let ty = match *value {
1211+
ParsedValue::Type(t) => t,
1212+
_ => Type::Any,
1213+
};
1214+
Ok(TypedParameter {
1215+
name,
1216+
ty,
1217+
mutability: Mutability::Immutable,
1218+
kind: ParameterKind::Regular,
1219+
default_value: None,
1220+
attributes: vec![],
1221+
span: Span::new(0, 0),
1222+
})
1223+
}
1224+
ParsedValue::Interned(name) => {
1225+
// Just a name, no type annotation
1226+
Ok(TypedParameter {
1227+
name,
1228+
ty: Type::Any,
1229+
mutability: Mutability::Immutable,
1230+
kind: ParameterKind::Regular,
1231+
default_value: None,
1232+
attributes: vec![],
1233+
span: Span::new(0, 0),
1234+
})
1235+
}
1236+
ParsedValue::Text(name) => {
1237+
let interned = state.intern(&name);
1238+
Ok(TypedParameter {
1239+
name: interned,
1240+
ty: Type::Any,
1241+
mutability: Mutability::Immutable,
1242+
kind: ParameterKind::Regular,
1243+
default_value: None,
1244+
attributes: vec![],
1245+
span: Span::new(0, 0),
1246+
})
1247+
}
1248+
_ => Err("cannot convert value to parameter".to_string()),
1249+
}
1250+
}
1251+
1252+
/// Get a field as a list of interned strings
1253+
fn get_field_as_interned_list<'a>(
1254+
&self,
1255+
name: &str,
1256+
fields: &[(String, ExprIR)],
1257+
state: &mut ParserState<'a>,
1258+
) -> Result<Vec<zyntax_typed_ast::InternedString>, String> {
1259+
match self.get_field(name, fields) {
1260+
Some(expr) => {
1261+
let val = self.eval_expr(expr, state)?;
1262+
match val {
1263+
ParsedValue::List(items) => {
1264+
let mut result = Vec::new();
1265+
for item in items {
1266+
let interned = self.parsed_value_to_interned(item, state)?;
1267+
result.push(interned);
1268+
}
1269+
Ok(result)
1270+
}
1271+
ParsedValue::None => Ok(vec![]),
1272+
ParsedValue::Optional(None) => Ok(vec![]),
1273+
ParsedValue::Optional(Some(inner)) => {
1274+
let interned = self.parsed_value_to_interned(*inner, state)?;
1275+
Ok(vec![interned])
1276+
}
1277+
ParsedValue::Interned(i) => Ok(vec![i]),
1278+
ParsedValue::Text(s) => Ok(vec![state.intern(&s)]),
1279+
_ => Err(format!("field '{}' is not an interned string list", name)),
1280+
}
1281+
}
1282+
None => Ok(vec![]),
1283+
}
1284+
}
1285+
1286+
/// Convert ParsedValue to InternedString
1287+
fn parsed_value_to_interned<'a>(
1288+
&self,
1289+
val: ParsedValue,
1290+
state: &mut ParserState<'a>,
1291+
) -> Result<zyntax_typed_ast::InternedString, String> {
1292+
match val {
1293+
ParsedValue::Interned(i) => Ok(i),
1294+
ParsedValue::Text(s) => Ok(state.intern(&s)),
1295+
_ => Err("cannot convert value to interned string".to_string()),
1296+
}
1297+
}
1298+
1299+
/// Get a field as a list of enum variants
1300+
fn get_field_as_variant_list<'a>(
1301+
&self,
1302+
name: &str,
1303+
fields: &[(String, ExprIR)],
1304+
state: &mut ParserState<'a>,
1305+
) -> Result<Vec<TypedVariant>, String> {
1306+
match self.get_field(name, fields) {
1307+
Some(expr) => {
1308+
let val = self.eval_expr(expr, state)?;
1309+
match val {
1310+
ParsedValue::List(items) => {
1311+
let mut result = Vec::new();
1312+
for item in items {
1313+
let variant = self.parsed_value_to_variant(item, state)?;
1314+
result.push(variant);
1315+
}
1316+
Ok(result)
1317+
}
1318+
ParsedValue::None => Ok(vec![]),
1319+
ParsedValue::Optional(None) => Ok(vec![]),
1320+
ParsedValue::Optional(Some(inner)) => {
1321+
match *inner {
1322+
ParsedValue::List(items) => {
1323+
let mut result = Vec::new();
1324+
for item in items {
1325+
let variant = self.parsed_value_to_variant(item, state)?;
1326+
result.push(variant);
1327+
}
1328+
Ok(result)
1329+
}
1330+
other => {
1331+
let variant = self.parsed_value_to_variant(other, state)?;
1332+
Ok(vec![variant])
1333+
}
1334+
}
1335+
}
1336+
ParsedValue::Variant(v) => Ok(vec![v]),
1337+
other => {
1338+
let variant = self.parsed_value_to_variant(other, state)?;
1339+
Ok(vec![variant])
1340+
}
1341+
}
1342+
}
1343+
None => Ok(vec![]),
1344+
}
1345+
}
1346+
1347+
/// Convert ParsedValue to TypedVariant
1348+
fn parsed_value_to_variant<'a>(
1349+
&self,
1350+
val: ParsedValue,
1351+
state: &mut ParserState<'a>,
1352+
) -> Result<TypedVariant, String> {
1353+
match val {
1354+
ParsedValue::Variant(v) => Ok(v),
1355+
ParsedValue::Interned(name) => {
1356+
// Simple unit variant (just a name)
1357+
Ok(TypedVariant {
1358+
name,
1359+
fields: TypedVariantFields::Unit,
1360+
discriminant: None,
1361+
span: Span::new(0, 0),
1362+
})
1363+
}
1364+
ParsedValue::Text(name) => {
1365+
let interned = state.intern(&name);
1366+
Ok(TypedVariant {
1367+
name: interned,
1368+
fields: TypedVariantFields::Unit,
1369+
discriminant: None,
1370+
span: Span::new(0, 0),
1371+
})
1372+
}
1373+
_ => Err("cannot convert value to variant".to_string()),
1374+
}
1375+
}
1376+
11011377
/// Convert ParsedValue to TypedExpression
11021378
fn parsed_value_to_expr<'a>(
11031379
&self,

crates/zyn_peg/src/runtime2/state.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ pub enum ParsedValue {
140140
name: InternedString,
141141
value: Box<ParsedValue>,
142142
},
143+
/// A function/method parameter
144+
Parameter(zyntax_typed_ast::TypedParameter),
145+
/// An enum variant
146+
Variant(zyntax_typed_ast::TypedVariant),
143147
}
144148

145149
/// Handle to an AST node (opaque, managed by builder)

0 commit comments

Comments
 (0)