From 864d125a72a2c56c3cf2e27ece51a79eeff8ecfd Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Sun, 05 Apr 2026 19:25:11 +0000 Subject: [PATCH] refactor(ir): flatten --- --- a/crates/jrsonnet-ir-parser/src/lib.rs +++ b/crates/jrsonnet-ir-parser/src/lib.rs @@ -1,13 +1,11 @@ -use std::rc::Rc; - use jrsonnet_gcmodule::Acyclic; use jrsonnet_ir::{ - ArgsDesc, AssertExpr, AssertStmt, BinaryOp, BinaryOpType, BindSpec, CompSpec, Destruct, Expr, - ExprParam, ExprParams, FieldMember, FieldName, ForSpecData, IStr, IfElse, IfSpecData, - ImportKind, IndexPart, LiteralType, Member, NumValue, ObjBody, ObjComp, ObjMembers, Slice, - SliceDesc, Source, Span, Spanned, UnaryOpType, Visibility, unescape, + unescape, ArgsDesc, AssertExpr, AssertStmt, BinaryOp, BinaryOpType, BindSpec, CompSpec, + Destruct, Expr, ExprParam, ExprParams, FieldMember, FieldName, ForSpecData, IStr, IfElse, + IfSpecData, ImportKind, IndexPart, LiteralType, Member, NumValue, ObjBody, ObjComp, ObjMembers, + Slice, SliceDesc, Source, Span, Spanned, UnaryOpType, Visibility, }; -use jrsonnet_lexer::{Lexeme, Lexer, Span as LexSpan, SyntaxKind, T, collect_lexed_str_block}; +use jrsonnet_lexer::{collect_lexed_str_block, Lexeme, Lexer, Span as LexSpan, SyntaxKind, T}; pub struct ParserSettings { pub source: Source, @@ -16,7 +14,7 @@ #[derive(Debug, Clone)] pub struct ParseError { pub message: String, - pub location: LexSpan, + pub location: Span, } impl std::fmt::Display for ParseError { @@ -128,12 +126,13 @@ if self.offset == self.lexemes.len() { let pos = self.lexemes.last().map_or(0, |v| v.range.1); return ParseError { - location: LexSpan(pos, pos), + location: Span(self.source.clone(), pos, pos), message, }; } + let LexSpan(start, end) = self.lexemes[self.offset].range; ParseError { - location: self.lexemes[self.offset].range, + location: Span(self.source.clone(), start, end), message, } } @@ -293,7 +292,7 @@ fn destruct(p: &mut Parser<'_>) -> Result { if p.at(SyntaxKind::IDENT) { - return Ok(Destruct::Full(ident(p)?)); + return Ok(Destruct::Full(spanned(p, ident)?)); } #[cfg(not(feature = "exp-destruct"))] return Err(p.error(format!("expected identifier, got {}", p.current_desc()))); @@ -407,7 +406,7 @@ loop { let d = destruct(p)?; let default = if p.try_eat(T![=]) { - Some(Rc::new(expr(p)?)) + Some(expr(p)?) } else { None }; @@ -441,16 +440,15 @@ if is_named { let name: IStr = ident(p)?; p.eat(T![=])?; - let value = Rc::new(expr(p)?); names.push(name); - values.push(value); + values.push(expr(p)?); named_started = true; } else { if named_started { return Err(p.error("positional argument after named argument".into())); } - unnamed.push(Rc::new(expr(p)?)); + unnamed.push(expr(p)?); } if !p.try_eat(T![,]) { break; @@ -472,23 +470,21 @@ return Ok(BindSpec::Field { into: d, value }); } } - let name = ident(p)?; + let name_spanned = spanned(p, ident)?; if p.try_eat(T!['(']) { let ps = params(p)?; p.eat(T![')'])?; p.eat(T![=])?; - let value = Rc::new(expr(p)?); Ok(BindSpec::Function { - name, + name: name_spanned.value, params: ps, - value, + value: expr(p)?, }) } else { p.eat(T![=])?; - let value = Rc::new(expr(p)?); Ok(BindSpec::Field { - into: Destruct::Full(name), - value, + into: Destruct::Full(name_spanned), + value: expr(p)?, }) } } @@ -529,24 +525,22 @@ let ps = params(p)?; p.eat(T![')'])?; let vis = visibility(p)?; - let value = Rc::new(expr(p)?); Ok(FieldMember { name, plus: false, params: Some(ps), visibility: vis, - value, + value: expr(p)?, }) } else { let plus = p.try_eat(T![+]); let vis = visibility(p)?; - let value = Rc::new(expr(p)?); Ok(FieldMember { name, plus, params: None, visibility: vis, - value, + value: expr(p)?, }) } } @@ -589,8 +583,8 @@ fn objinside(p: &mut Parser<'_>) -> Result { if p.at(T!['}']) { return Ok(ObjBody::MemberList(ObjMembers { - locals: Rc::new(Vec::new()), - asserts: Rc::new(Vec::new()), + locals: Vec::new(), + asserts: Vec::new(), fields: Vec::new(), })); } @@ -627,8 +621,8 @@ } } Ok(ObjBody::ObjComp(ObjComp { - locals: Rc::new(locals), - field: Rc::new( + locals, + field: Box::new( field_member.ok_or_else(|| p.error("missing object comprehension field".into()))?, ), compspecs: specs, @@ -645,8 +639,8 @@ } } Ok(ObjBody::MemberList(ObjMembers { - locals: Rc::new(locals), - asserts: Rc::new(asserts), + locals, + asserts, fields, })) } @@ -678,13 +672,13 @@ p.eat(T!['['])?; if p.at(T![']']) { p.eat(T![']'])?; - return Ok(Expr::Arr(Rc::new(Vec::new()))); + return Ok(Expr::Arr(Vec::new())); } let first = expr(p)?; if p.at(T![for]) { let specs = compspecs(p)?; p.eat(T![']'])?; - Ok(Expr::ArrComp(Rc::new(first), specs)) + Ok(Expr::ArrComp(Box::new(first), specs)) } else if p.at(T![,]) && { let next = p.offset + 1; next < p.lexemes.len() && p.lexemes[next].kind == T![for] @@ -692,7 +686,7 @@ p.eat(T![,])?; let specs = compspecs(p)?; p.eat(T![']'])?; - Ok(Expr::ArrComp(Rc::new(first), specs)) + Ok(Expr::ArrComp(Box::new(first), specs)) } else { let mut elems = vec![first]; while p.try_eat(T![,]) { @@ -702,7 +696,7 @@ elems.push(expr(p)?); } p.eat(T![']'])?; - Ok(Expr::Arr(Rc::new(elems))) + Ok(Expr::Arr(elems)) } } @@ -735,14 +729,14 @@ let ps = params(p)?; p.eat(T![')'])?; let body = expr(p)?; - Ok(Expr::Function(ps, Rc::new(body))) + Ok(Expr::Function(ps, Box::new(body))) } T![assert] => { let a = assert_stmt(p)?; p.eat(T![;])?; let rest = expr(p)?; - Ok(Expr::AssertExpr(Rc::new(AssertExpr { assert: a, rest }))) + Ok(Expr::AssertExpr(Box::new(AssertExpr { assert: a, rest }))) } T![error] => { @@ -891,7 +885,7 @@ p.eat(T!['{'])?; let body = objinside(p)?; p.eat(T!['}'])?; - e = Expr::ObjExtend(Rc::new(e), body); + e = Expr::ObjExtend(Box::new(e), body); } else { break; } @@ -1007,7 +1001,7 @@ if let Some(desc) = lexeme.kind.error_description() { return Err(ParseError { message: desc.to_owned(), - location: lexeme.range, + location: Span(p.source.clone(), lexeme.range.0, lexeme.range.1), }); } } --- a/crates/jrsonnet-ir-parser/src/snapshots/jrsonnet_ir_parser__tests__array_comp.snap +++ b/crates/jrsonnet-ir-parser/src/snapshots/jrsonnet_ir_parser__tests__array_comp.snap @@ -10,7 +10,7 @@ ForSpec( ForSpecData { destruct: Full( - "x", + "x" from virtual::7-8, ), over: Var( "arr" from virtual::12-15, --- a/crates/jrsonnet-ir-parser/src/snapshots/jrsonnet_ir_parser__tests__function_and_call.snap +++ b/crates/jrsonnet-ir-parser/src/snapshots/jrsonnet_ir_parser__tests__function_and_call.snap @@ -10,13 +10,13 @@ exprs: [ ExprParam { destruct: Full( - "x", + "x" from virtual::8-9, ), default: None, }, ExprParam { destruct: Full( - "y", + "y" from virtual::11-12, ), default: Some( Num( --- a/crates/jrsonnet-ir-parser/src/snapshots/jrsonnet_ir_parser__tests__peg_snapshots@array_comp.jsonnet.snap +++ b/crates/jrsonnet-ir-parser/src/snapshots/jrsonnet_ir_parser__tests__peg_snapshots@array_comp.jsonnet.snap @@ -35,7 +35,7 @@ ForSpec( ForSpecData { destruct: Full( - "x", + "x" from virtual::23-24, ), over: Var( "arr" from virtual::28-31, @@ -52,7 +52,7 @@ ForSpec( ForSpecData { destruct: Full( - "a", + "a" from virtual::41-42, ), over: Var( "b" from virtual::46-47, @@ -70,7 +70,7 @@ ForSpec( ForSpecData { destruct: Full( - "e", + "e" from virtual::57-58, ), over: Var( "f" from virtual::62-63, --- a/crates/jrsonnet-ir-parser/src/snapshots/jrsonnet_ir_parser__tests__peg_snapshots@default_nondefault.jsonnet.snap +++ b/crates/jrsonnet-ir-parser/src/snapshots/jrsonnet_ir_parser__tests__peg_snapshots@default_nondefault.jsonnet.snap @@ -11,7 +11,7 @@ exprs: [ ExprParam { destruct: Full( - "foo", + "foo" from virtual::8-11, ), default: Some( Str( @@ -21,7 +21,7 @@ }, ExprParam { destruct: Full( - "bar", + "bar" from virtual::21-24, ), default: None, }, --- a/crates/jrsonnet-ir-parser/src/snapshots/jrsonnet_ir_parser__tests__peg_snapshots@subexp.jsonnet.snap +++ b/crates/jrsonnet-ir-parser/src/snapshots/jrsonnet_ir_parser__tests__peg_snapshots@subexp.jsonnet.snap @@ -20,7 +20,7 @@ locals: [ Field { into: Full( - "x", + "x" from virtual::11-12, ), value: Num( 1.0, --- a/crates/jrsonnet-ir/src/expr.rs +++ b/crates/jrsonnet-ir/src/expr.rs @@ -1,16 +1,15 @@ use std::{ fmt::{self, Debug, Display}, ops::{Deref, RangeInclusive}, - rc::Rc, }; use jrsonnet_gcmodule::Acyclic; use jrsonnet_interner::IStr; use crate::{ - NumValue, function::{FunctionSignature, ParamDefault, ParamName, ParamParse}, source::Source, + NumValue, }; #[derive(Debug, PartialEq, Acyclic)] @@ -50,7 +49,7 @@ pub plus: bool, pub params: Option, pub visibility: Visibility, - pub value: Rc, + pub value: Expr, } #[derive(Debug, PartialEq, Acyclic)] @@ -156,13 +155,13 @@ #[derive(Debug, PartialEq, Acyclic)] pub struct ExprParam { pub destruct: Destruct, - pub default: Option>, + pub default: Option, } /// Defined function parameters -#[derive(Debug, Clone, PartialEq, Acyclic)] +#[derive(Debug, PartialEq, Acyclic)] pub struct ExprParams { - pub exprs: Rc>, + pub exprs: Vec, pub signature: FunctionSignature, pub(crate) binds_len: usize, } @@ -191,19 +190,19 @@ .collect(), ), binds_len: exprs.iter().map(|v| v.destruct.binds_len()).sum(), - exprs: Rc::new(exprs), + exprs, } } } #[derive(Debug, PartialEq, Acyclic)] pub struct ArgsDesc { - pub unnamed: Vec>, + pub unnamed: Vec, pub names: Vec, - pub values: Vec>, + pub values: Vec, } impl ArgsDesc { - pub fn new(unnamed: Vec>, names: Vec, values: Vec>) -> Self { + pub fn new(unnamed: Vec, names: Vec, values: Vec) -> Self { Self { unnamed, names, @@ -222,7 +221,7 @@ #[derive(Debug, Clone, PartialEq, Acyclic)] pub enum Destruct { - Full(IStr), + Full(Spanned), #[cfg(feature = "exp-destruct")] Skip, #[cfg(feature = "exp-destruct")] @@ -242,7 +241,7 @@ /// Name of destructure, used for function parameter names pub fn name(&self) -> ParamName { match self { - Self::Full(name) => ParamName::Named(name.clone()), + Self::Full(name) => ParamName::Named(name.value.clone()), #[cfg(feature = "exp-destruct")] _ => ParamName::Unnamed, } @@ -286,12 +285,12 @@ pub enum BindSpec { Field { into: Destruct, - value: Rc, + value: Expr, }, Function { name: IStr, params: ExprParams, - value: Rc, + value: Expr, }, } impl BindSpec { @@ -323,15 +322,15 @@ #[derive(Debug, PartialEq, Acyclic)] pub struct ObjComp { - pub locals: Rc>, - pub field: Rc, + pub locals: Vec, + pub field: Box, pub compspecs: Vec, } #[derive(Debug, PartialEq, Acyclic)] pub struct ObjMembers { - pub locals: Rc>, - pub asserts: Rc>, + pub locals: Vec, + pub asserts: Vec, pub fields: Vec, } @@ -371,7 +370,7 @@ pub rhs: Expr, } -#[derive(Debug, PartialEq, Acyclic)] +#[derive(Debug, PartialEq, Acyclic, Clone, Copy)] pub enum ImportKind { Normal, Str, @@ -404,7 +403,7 @@ Var(Spanned), /// Array of expressions: [1, 2, "Hello"] - Arr(Rc>), + Arr(Vec), /// Array comprehension: /// ```jsonnet /// ingredients: [ @@ -416,19 +415,19 @@ /// ] /// ], /// ``` - ArrComp(Rc, Vec), + ArrComp(Box, Vec), /// Object: {a: 2} Obj(ObjBody), /// Object extension: var1 {b: 2} - ObjExtend(Rc, ObjBody), + ObjExtend(Box, ObjBody), /// -2 UnaryOp(UnaryOpType, Box), /// 2 - 2 BinaryOp(Box), /// assert 2 == 2 : "Math is broken" - AssertExpr(Rc), + AssertExpr(Box), /// local a = 2; { b: a } LocalExpr(Vec, Box), @@ -444,7 +443,7 @@ parts: Vec, }, /// function(x) x - Function(ExprParams, Rc), + Function(ExprParams, Box), /// if true == false then 1 else 2 IfElse(Box), Slice(Box), --- a/crates/jrsonnet-peg-parser/src/lib.rs +++ b/crates/jrsonnet-peg-parser/src/lib.rs @@ -61,13 +61,13 @@ rule keyword(id: &'static str) -> () = #{|input, pos| input.parse_string_literal(pos, id)} end_of_ident() - pub rule param(s: &ParserSettings) -> ExprParam = destruct:destruct(s) expr:(_ "=" _ expr:expr(s){expr})? { ExprParam { destruct, default: expr.map(Rc::new) } } + pub rule param(s: &ParserSettings) -> ExprParam = destruct:destruct(s) default:(_ "=" _ default:expr(s){default})? { ExprParam { destruct, default } } pub rule params(s: &ParserSettings) -> ExprParams = params:param(s) ** comma() comma()? { ExprParams::new(params) } / { ExprParams::new(Vec::new()) } - pub rule arg(s: &ParserSettings) -> (Option, Rc) - = name:(quiet! { (s:id() _ "=" !['='] _ {s})? } / expected!("")) expr:expr(s) {(name, Rc::new(expr))} + pub rule arg(s: &ParserSettings) -> (Option, Expr) + = name:(quiet! { (s:id() _ "=" !['='] _ {s})? } / expected!("")) expr:expr(s) {(name, expr)} pub rule args(s: &ParserSettings) -> ArgsDesc = args:arg(s)**comma() comma()? {? @@ -123,7 +123,7 @@ #[cfg(not(feature = "exp-destruct"))] Err("!!!experimental destructuring was not enabled") } pub rule destruct(s: &ParserSettings) -> Destruct - = v:id() {Destruct::Full(v)} + = v:spanned(, s) {Destruct::Full(v)} / "?" {? #[cfg(feature = "exp-destruct")] return Ok(Destruct::Skip); #[cfg(not(feature = "exp-destruct"))] Err("!!!experimental destructuring was not enabled") @@ -132,8 +132,8 @@ / obj:destruct_object(s) {obj} pub rule bind(s: &ParserSettings) -> BindSpec - = into:destruct(s) _ "=" _ value:expr(s) {BindSpec::Field{into, value: Rc::new(value)}} - / name:id() _ "(" _ params:params(s) _ ")" _ "=" _ value:expr(s) {BindSpec::Function{name, params, value: Rc::new(value)}} + = into:destruct(s) _ "=" _ value:expr(s) {BindSpec::Field{into, value}} + / name:id() _ "(" _ params:params(s) _ ")" _ "=" _ value:expr(s) {BindSpec::Function{name, params, value}} pub rule assertion(s: &ParserSettings) -> AssertStmt = keyword("assert") _ assertion:spanned(, s) message:(_ ":" _ e:expr(s) {e})? { AssertStmt{assertion, message} } @@ -187,14 +187,14 @@ plus: plus.is_some(), params: None, visibility, - value: Rc::new(value), + value, }} / name:spanned(, s) _ "(" _ params:params(s) _ ")" _ visibility:visibility() _ value:expr(s) {FieldMember{ name, plus: false, params: Some(params), visibility, - value: Rc::new(value), + value, }} pub rule obj_local(s: &ParserSettings) -> BindSpec = keyword("local") _ bind:bind(s) {bind} @@ -217,8 +217,8 @@ } } ObjBody::ObjComp(ObjComp { - locals: Rc::new(locals), - field: field.map(Rc::new).ok_or("")?, + locals, + field: Box::new(field.ok_or("")?), compspecs }) } else { @@ -233,8 +233,8 @@ } } ObjBody::MemberList(ObjMembers { - locals: Rc::new(locals), - asserts: Rc::new(asserts), + locals, + asserts, fields }) }) @@ -259,10 +259,10 @@ pub rule obj_expr(s: &ParserSettings) -> Expr = "{" _ body:objinside(s) _ "}" {Expr::Obj(body)} pub rule array_expr(s: &ParserSettings) -> Expr - = "[" _ elems:(expr(s) ** comma()) _ comma()? "]" {Expr::Arr(Rc::new(elems))} + = "[" _ elems:(expr(s) ** comma()) _ comma()? "]" {Expr::Arr(elems)} pub rule array_comp_expr(s: &ParserSettings) -> Expr = "[" _ expr:expr(s) _ comma()? _ specs:(r: compspecs(s) _ {r}) "]" { - Expr::ArrComp(Rc::new(expr), specs) + Expr::ArrComp(Box::new(expr), specs) } pub rule number_expr(s: &ParserSettings) -> Expr = n:number() {? if let Some(n) = NumValue::new(n) { @@ -315,8 +315,8 @@ / local_expr(s) / if_then_else_expr(s) - / keyword("function") _ "(" _ params:params(s) _ ")" _ expr:expr(s) {Expr::Function(params, Rc::new(expr))} - / assert:assertion(s) _ ";" _ rest:expr(s) { Expr::AssertExpr(Rc::new(AssertExpr{ + / keyword("function") _ "(" _ params:params(s) _ ")" _ expr:expr(s) {Expr::Function(params, Box::new(expr))} + / assert:assertion(s) _ ";" _ rest:expr(s) { Expr::AssertExpr(Box::new(AssertExpr{ assert, rest })) } @@ -390,7 +390,7 @@ value:(@) _ "[" _ slice:slice_desc(s) _ "]" {Expr::Slice(Box::new(Slice{value, slice}))} indexable:(@) _ parts:index_part(s)+ {Expr::Index{indexable: Box::new(indexable), parts}} a:(@) _ args:spanned(<"(" _ a:args(s) _ ")" {a}>, s) ts:(_ keyword("tailstrict"))? {Expr::Apply(Box::new(a), args, ts.is_some())} - a:(@) _ "{" _ body:objinside(s) _ "}" {Expr::ObjExtend(Rc::new(a), body)} + a:(@) _ "{" _ body:objinside(s) _ "}" {Expr::ObjExtend(Box::new(a), body)} -- e:expr_basic(s) {e} "(" _ e:expr(s) _ ")" {e} --- a/crates/jrsonnet-peg-parser/src/snapshots/jrsonnet_peg_parser__tests__snapshots@array_comp.jsonnet.snap +++ b/crates/jrsonnet-peg-parser/src/snapshots/jrsonnet_peg_parser__tests__snapshots@array_comp.jsonnet.snap @@ -35,7 +35,7 @@ ForSpec( ForSpecData { destruct: Full( - "x", + "x" from virtual::23-24, ), over: Var( "arr" from virtual::28-31, @@ -52,7 +52,7 @@ ForSpec( ForSpecData { destruct: Full( - "a", + "a" from virtual::41-42, ), over: Var( "b" from virtual::46-47, @@ -70,7 +70,7 @@ ForSpec( ForSpecData { destruct: Full( - "e", + "e" from virtual::57-58, ), over: Var( "f" from virtual::62-63, --- a/crates/jrsonnet-peg-parser/src/snapshots/jrsonnet_peg_parser__tests__snapshots@default_nondefault.jsonnet.snap +++ b/crates/jrsonnet-peg-parser/src/snapshots/jrsonnet_peg_parser__tests__snapshots@default_nondefault.jsonnet.snap @@ -11,7 +11,7 @@ exprs: [ ExprParam { destruct: Full( - "foo", + "foo" from virtual::8-11, ), default: Some( Str( @@ -21,7 +21,7 @@ }, ExprParam { destruct: Full( - "bar", + "bar" from virtual::21-24, ), default: None, }, --- a/crates/jrsonnet-peg-parser/src/snapshots/jrsonnet_peg_parser__tests__snapshots@subexp.jsonnet.snap +++ b/crates/jrsonnet-peg-parser/src/snapshots/jrsonnet_peg_parser__tests__snapshots@subexp.jsonnet.snap @@ -20,7 +20,7 @@ locals: [ Field { into: Full( - "x", + "x" from virtual::11-12, ), value: Num( 1.0, -- gitstuff