Convert span's start to line number + col
This requires to make line numbers a first-class citizen in the module hierarchy but it is fortunately not _too involved_.
This commit is contained in:
		
							parent
							
								
									e67d5863a1
								
							
						
					
					
						commit
						59c784778e
					
				|  | @ -1,6 +1,7 @@ | |||
| use crate::{ | ||||
|     builtins::{self, bool, g1_element, g2_element}, | ||||
|     expr::{TypedExpr, UntypedExpr}, | ||||
|     line_numbers::LineNumbers, | ||||
|     parser::token::{Base, Token}, | ||||
|     tipo::{PatternConstructor, Type, TypeInfo}, | ||||
| }; | ||||
|  | @ -42,6 +43,7 @@ pub struct Module<Info, Definitions> { | |||
|     pub docs: Vec<String>, | ||||
|     pub type_info: Info, | ||||
|     pub definitions: Vec<Definitions>, | ||||
|     pub lines: LineNumbers, | ||||
|     pub kind: ModuleKind, | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -27,10 +27,11 @@ use crate::{ | |||
|     gen_uplc::builder::{ | ||||
|         check_replaceable_opaque_type, convert_opaque_type, erase_opaque_type_operations, | ||||
|         find_and_replace_generics, find_list_clause_or_default_first, get_arg_type_name, | ||||
|         get_generic_id_and_type, get_generic_variant_name, get_src_code_by_span, monomorphize, | ||||
|         pattern_has_conditions, wrap_as_multi_validator, wrap_validator_condition, CodeGenFunction, | ||||
|         SpecificClause, | ||||
|         get_generic_id_and_type, get_generic_variant_name, get_line_columns_by_span, | ||||
|         get_src_code_by_span, monomorphize, pattern_has_conditions, wrap_as_multi_validator, | ||||
|         wrap_validator_condition, CodeGenFunction, SpecificClause, | ||||
|     }, | ||||
|     line_numbers::LineNumbers, | ||||
|     tipo::{ | ||||
|         ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor, | ||||
|         ValueConstructorVariant, | ||||
|  | @ -55,7 +56,7 @@ pub struct CodeGenerator<'a> { | |||
|     functions: IndexMap<FunctionAccessKey, &'a TypedFunction>, | ||||
|     data_types: IndexMap<DataTypeKey, &'a TypedDataType>, | ||||
|     module_types: IndexMap<&'a String, &'a TypeInfo>, | ||||
|     module_src: IndexMap<String, String>, | ||||
|     module_src: IndexMap<String, (String, LineNumbers)>, | ||||
|     /// immutable option
 | ||||
|     tracing: TraceLevel, | ||||
|     /// mutable index maps that are reset
 | ||||
|  | @ -74,7 +75,7 @@ impl<'a> CodeGenerator<'a> { | |||
|         functions: IndexMap<FunctionAccessKey, &'a TypedFunction>, | ||||
|         data_types: IndexMap<DataTypeKey, &'a TypedDataType>, | ||||
|         module_types: IndexMap<&'a String, &'a TypeInfo>, | ||||
|         module_src: IndexMap<String, String>, | ||||
|         module_src: IndexMap<String, (String, LineNumbers)>, | ||||
|         tracing: TraceLevel, | ||||
|     ) -> Self { | ||||
|         CodeGenerator { | ||||
|  | @ -132,10 +133,10 @@ impl<'a> CodeGenerator<'a> { | |||
| 
 | ||||
|         air_tree_fun = wrap_validator_condition(air_tree_fun, self.tracing); | ||||
| 
 | ||||
|         let src_code = self.module_src.get(module_name).unwrap().clone(); | ||||
|         let (src_code, lines) = self.module_src.get(module_name).unwrap().clone(); | ||||
| 
 | ||||
|         let mut validator_args_tree = | ||||
|             self.check_validator_args(&fun.arguments, true, air_tree_fun, &src_code); | ||||
|             self.check_validator_args(&fun.arguments, true, air_tree_fun, &src_code, &lines); | ||||
| 
 | ||||
|         validator_args_tree = AirTree::no_op().hoist_over(validator_args_tree); | ||||
| 
 | ||||
|  | @ -154,8 +155,13 @@ impl<'a> CodeGenerator<'a> { | |||
| 
 | ||||
|             air_tree_fun_other = wrap_validator_condition(air_tree_fun_other, self.tracing); | ||||
| 
 | ||||
|             let mut validator_args_tree_other = | ||||
|                 self.check_validator_args(&other.arguments, true, air_tree_fun_other, &src_code); | ||||
|             let mut validator_args_tree_other = self.check_validator_args( | ||||
|                 &other.arguments, | ||||
|                 true, | ||||
|                 air_tree_fun_other, | ||||
|                 &src_code, | ||||
|                 &lines, | ||||
|             ); | ||||
| 
 | ||||
|             validator_args_tree_other = AirTree::no_op().hoist_over(validator_args_tree_other); | ||||
| 
 | ||||
|  | @ -474,8 +480,12 @@ impl<'a> CodeGenerator<'a> { | |||
|                         if kind.is_expect() { | ||||
|                             let msg = match self.tracing { | ||||
|                                 TraceLevel::Silent => unreachable!("excluded from pattern guards"), | ||||
|                                 // TODO: line number & col
 | ||||
|                                 TraceLevel::Compact => format!("{}", location.start), | ||||
|                                 TraceLevel::Compact => get_line_columns_by_span( | ||||
|                                     module_name, | ||||
|                                     location, | ||||
|                                     &self.module_src, | ||||
|                                 ) | ||||
|                                 .to_string(), | ||||
|                                 TraceLevel::Verbose => { | ||||
|                                     get_src_code_by_span(module_name, location, &self.module_src) | ||||
|                                 } | ||||
|  | @ -2746,6 +2756,7 @@ impl<'a> CodeGenerator<'a> { | |||
|         has_context: bool, | ||||
|         body: AirTree, | ||||
|         src_code: &str, | ||||
|         lines: &LineNumbers, | ||||
|     ) -> AirTree { | ||||
|         let checked_args = arguments | ||||
|             .iter() | ||||
|  | @ -2764,8 +2775,10 @@ impl<'a> CodeGenerator<'a> { | |||
|                         TraceLevel::Compact | TraceLevel::Verbose => { | ||||
|                             let msg = match self.tracing { | ||||
|                                 TraceLevel::Silent => unreachable!("excluded from pattern guards"), | ||||
|                                 // TODO: Show line number + column
 | ||||
|                                 TraceLevel::Compact => format!("{}", arg_span.start), | ||||
|                                 TraceLevel::Compact => lines | ||||
|                                     .line_and_column_number(arg_span.start) | ||||
|                                     .expect("Out of bounds span") | ||||
|                                     .to_string(), | ||||
|                                 TraceLevel::Verbose => src_code | ||||
|                                     .get(arg_span.start..arg_span.end) | ||||
|                                     .expect("Out of bounds span") | ||||
|  |  | |||
|  | @ -20,6 +20,7 @@ use crate::{ | |||
|     }, | ||||
|     builtins::{bool, data, function, int, list, string, void}, | ||||
|     expr::TypedExpr, | ||||
|     line_numbers::{LineColumn, LineNumbers}, | ||||
|     tipo::{PatternConstructor, TypeVar, ValueConstructor, ValueConstructorVariant}, | ||||
| }; | ||||
| 
 | ||||
|  | @ -1775,9 +1776,9 @@ pub fn extract_constant(term: &Term<Name>) -> Option<Rc<UplcConstant>> { | |||
| pub fn get_src_code_by_span( | ||||
|     module_name: &String, | ||||
|     span: &Span, | ||||
|     module_src: &IndexMap<String, String>, | ||||
|     module_src: &IndexMap<String, (String, LineNumbers)>, | ||||
| ) -> String { | ||||
|     let src = module_src | ||||
|     let (src, _) = module_src | ||||
|         .get(module_name) | ||||
|         .unwrap_or_else(|| panic!("Missing module {module_name}")); | ||||
| 
 | ||||
|  | @ -1786,6 +1787,20 @@ pub fn get_src_code_by_span( | |||
|         .to_string() | ||||
| } | ||||
| 
 | ||||
| pub fn get_line_columns_by_span( | ||||
|     module_name: &String, | ||||
|     span: &Span, | ||||
|     module_src: &IndexMap<String, (String, LineNumbers)>, | ||||
| ) -> LineColumn { | ||||
|     let (_, lines) = module_src | ||||
|         .get(module_name) | ||||
|         .unwrap_or_else(|| panic!("Missing module {module_name}")); | ||||
| 
 | ||||
|     lines | ||||
|         .line_and_column_number(span.start) | ||||
|         .expect("Out of bounds span") | ||||
| } | ||||
| 
 | ||||
| pub fn air_holds_msg(air: &Air) -> bool { | ||||
|     match air { | ||||
|         Air::AssertConstr { .. } | Air::AssertBool { .. } | Air::FieldsEmpty | Air::ListEmpty => { | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| use std::fmt::{self, Display}; | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| #[derive(Debug, PartialEq, Eq, Clone)] | ||||
| pub struct LineNumbers { | ||||
|     line_starts: Vec<usize>, | ||||
|     length: usize, | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ pub use definition::parser as definition; | |||
| pub use expr::parser as expression; | ||||
| pub use pattern::parser as pattern; | ||||
| 
 | ||||
| use crate::ast; | ||||
| use crate::{ast, line_numbers::LineNumbers}; | ||||
| use chumsky::prelude::*; | ||||
| use error::ParseError; | ||||
| use extra::ModuleExtra; | ||||
|  | @ -30,8 +30,11 @@ pub fn module( | |||
| 
 | ||||
|     let definitions = definition().repeated().then_ignore(end()).parse(stream)?; | ||||
| 
 | ||||
|     let lines = LineNumbers::new(src); | ||||
| 
 | ||||
|     let module = ast::UntypedModule { | ||||
|         kind, | ||||
|         lines, | ||||
|         definitions, | ||||
|         docs: vec![], | ||||
|         name: "".to_string(), | ||||
|  |  | |||
|  | @ -19,5 +19,17 @@ Module { | |||
|             }, | ||||
|         ), | ||||
|     ], | ||||
|     lines: LineNumbers { | ||||
|         line_starts: [ | ||||
|             0, | ||||
|             10, | ||||
|             11, | ||||
|             27, | ||||
|         ], | ||||
|         length: 43, | ||||
|         last: Some( | ||||
|             27, | ||||
|         ), | ||||
|     }, | ||||
|     kind: Validator, | ||||
| } | ||||
|  |  | |||
|  | @ -197,5 +197,32 @@ Module { | |||
|             }, | ||||
|         ), | ||||
|     ], | ||||
|     lines: LineNumbers { | ||||
|         line_starts: [ | ||||
|             0, | ||||
|             13, | ||||
|             27, | ||||
|             34, | ||||
|             36, | ||||
|             37, | ||||
|             50, | ||||
|             64, | ||||
|             71, | ||||
|             73, | ||||
|             74, | ||||
|             87, | ||||
|             104, | ||||
|             106, | ||||
|             107, | ||||
|             120, | ||||
|             138, | ||||
|             154, | ||||
|             156, | ||||
|         ], | ||||
|         length: 156, | ||||
|         last: Some( | ||||
|             156, | ||||
|         ), | ||||
|     }, | ||||
|     kind: Validator, | ||||
| } | ||||
|  |  | |||
|  | @ -48,5 +48,18 @@ Module { | |||
|             }, | ||||
|         ), | ||||
|     ], | ||||
|     lines: LineNumbers { | ||||
|         line_starts: [ | ||||
|             0, | ||||
|             11, | ||||
|             27, | ||||
|             31, | ||||
|             33, | ||||
|         ], | ||||
|         length: 33, | ||||
|         last: Some( | ||||
|             33, | ||||
|         ), | ||||
|     }, | ||||
|     kind: Validator, | ||||
| } | ||||
|  |  | |||
|  | @ -46,5 +46,18 @@ Module { | |||
|             }, | ||||
|         ), | ||||
|     ], | ||||
|     lines: LineNumbers { | ||||
|         line_starts: [ | ||||
|             0, | ||||
|             11, | ||||
|             25, | ||||
|             29, | ||||
|             31, | ||||
|         ], | ||||
|         length: 31, | ||||
|         last: Some( | ||||
|             31, | ||||
|         ), | ||||
|     }, | ||||
|     kind: Validator, | ||||
| } | ||||
|  |  | |||
|  | @ -20,5 +20,15 @@ Module { | |||
|             }, | ||||
|         ), | ||||
|     ], | ||||
|     lines: LineNumbers { | ||||
|         line_starts: [ | ||||
|             0, | ||||
|             16, | ||||
|         ], | ||||
|         length: 16, | ||||
|         last: Some( | ||||
|             16, | ||||
|         ), | ||||
|     }, | ||||
|     kind: Validator, | ||||
| } | ||||
|  |  | |||
|  | @ -1,3 +1,4 @@ | |||
| use crate::line_numbers::LineNumbers; | ||||
| use std::{cmp::Ordering, collections::HashMap, rc::Rc}; | ||||
| use vec1::Vec1; | ||||
| 
 | ||||
|  | @ -26,6 +27,8 @@ use super::{ | |||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub(crate) struct ExprTyper<'a, 'b> { | ||||
|     pub(crate) lines: &'a LineNumbers, | ||||
| 
 | ||||
|     pub(crate) environment: &'a mut Environment<'b>, | ||||
| 
 | ||||
|     // We tweak the tracing behavior during type-check. Traces are either kept or left out of the
 | ||||
|  | @ -435,7 +438,11 @@ impl<'a, 'b> ExprTyper<'a, 'b> { | |||
|             TraceLevel::Compact => Some(TypedExpr::String { | ||||
|                 location, | ||||
|                 tipo: string(), | ||||
|                 value: format!("{}", location.start), | ||||
|                 value: self | ||||
|                     .lines | ||||
|                     .line_and_column_number(location.start) | ||||
|                     .expect("Spans are within bounds.") | ||||
|                     .to_string(), | ||||
|             }), | ||||
|             TraceLevel::Silent => None, | ||||
|         }; | ||||
|  | @ -1827,7 +1834,6 @@ impl<'a, 'b> ExprTyper<'a, 'b> { | |||
| 
 | ||||
|         match self.tracing.trace_level(false) { | ||||
|             TraceLevel::Silent => Ok(then), | ||||
|             // TODO: use line numbers & cols
 | ||||
|             TraceLevel::Compact => Ok(TypedExpr::Trace { | ||||
|                 location, | ||||
|                 tipo, | ||||
|  | @ -1835,7 +1841,11 @@ impl<'a, 'b> ExprTyper<'a, 'b> { | |||
|                 text: Box::new(TypedExpr::String { | ||||
|                     location, | ||||
|                     tipo: string(), | ||||
|                     value: format!("{}", location.start), | ||||
|                     value: self | ||||
|                         .lines | ||||
|                         .line_and_column_number(location.start) | ||||
|                         .expect("Spans are within bounds.") | ||||
|                         .to_string(), | ||||
|                 }), | ||||
|             }), | ||||
|             TraceLevel::Verbose => Ok(TypedExpr::Trace { | ||||
|  | @ -1995,12 +2005,17 @@ impl<'a, 'b> ExprTyper<'a, 'b> { | |||
|         self.environment.instantiate(t, ids, &self.hydrator) | ||||
|     } | ||||
| 
 | ||||
|     pub fn new(environment: &'a mut Environment<'b>, tracing: Tracing) -> Self { | ||||
|     pub fn new( | ||||
|         environment: &'a mut Environment<'b>, | ||||
|         lines: &'a LineNumbers, | ||||
|         tracing: Tracing, | ||||
|     ) -> Self { | ||||
|         Self { | ||||
|             hydrator: Hydrator::new(), | ||||
|             environment, | ||||
|             tracing, | ||||
|             ungeneralised_function_used: false, | ||||
|             lines, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ use crate::{ | |||
|     }, | ||||
|     builtins, | ||||
|     builtins::function, | ||||
|     line_numbers::LineNumbers, | ||||
|     IdGenerator, | ||||
| }; | ||||
| 
 | ||||
|  | @ -79,8 +80,14 @@ impl UntypedModule { | |||
|         } | ||||
| 
 | ||||
|         for def in consts.into_iter().chain(not_consts) { | ||||
|             let definition = | ||||
|                 infer_definition(def, &name, &mut hydrators, &mut environment, tracing)?; | ||||
|             let definition = infer_definition( | ||||
|                 def, | ||||
|                 &name, | ||||
|                 &mut hydrators, | ||||
|                 &mut environment, | ||||
|                 &self.lines, | ||||
|                 tracing, | ||||
|             )?; | ||||
|             definitions.push(definition); | ||||
|         } | ||||
| 
 | ||||
|  | @ -127,6 +134,7 @@ impl UntypedModule { | |||
|             name: name.clone(), | ||||
|             definitions, | ||||
|             kind, | ||||
|             lines: self.lines, | ||||
|             type_info: TypeInfo { | ||||
|                 name, | ||||
|                 types, | ||||
|  | @ -145,6 +153,7 @@ fn infer_definition( | |||
|     module_name: &String, | ||||
|     hydrators: &mut HashMap<String, Hydrator>, | ||||
|     environment: &mut Environment<'_>, | ||||
|     lines: &LineNumbers, | ||||
|     tracing: Tracing, | ||||
| ) -> Result<TypedDefinition, Error> { | ||||
|     match def { | ||||
|  | @ -181,7 +190,7 @@ fn infer_definition( | |||
|                         .map(|(arg_name, tipo)| arg_name.set_type(tipo.clone())) | ||||
|                         .collect(); | ||||
| 
 | ||||
|                     let mut expr_typer = ExprTyper::new(environment, tracing); | ||||
|                     let mut expr_typer = ExprTyper::new(environment, lines, tracing); | ||||
| 
 | ||||
|                     expr_typer.hydrator = hydrators | ||||
|                         .remove(&name) | ||||
|  | @ -293,6 +302,7 @@ fn infer_definition( | |||
|                     module_name, | ||||
|                     hydrators, | ||||
|                     environment, | ||||
|                     lines, | ||||
|                     tracing, | ||||
|                 )? | ||||
|                 else { | ||||
|  | @ -343,6 +353,7 @@ fn infer_definition( | |||
|                             module_name, | ||||
|                             hydrators, | ||||
|                             environment, | ||||
|                             lines, | ||||
|                             tracing, | ||||
|                         )? | ||||
|                         else { | ||||
|  | @ -404,6 +415,7 @@ fn infer_definition( | |||
|                 module_name, | ||||
|                 hydrators, | ||||
|                 environment, | ||||
|                 lines, | ||||
|                 tracing, | ||||
|             )? { | ||||
|                 environment.unify(f.return_type.clone(), builtins::bool(), f.location, false)?; | ||||
|  | @ -585,7 +597,7 @@ fn infer_definition( | |||
|             .. | ||||
|         }) => { | ||||
|             let typed_expr = | ||||
|                 ExprTyper::new(environment, tracing).infer_const(&annotation, *value)?; | ||||
|                 ExprTyper::new(environment, lines, tracing).infer_const(&annotation, *value)?; | ||||
| 
 | ||||
|             let tipo = typed_expr.tipo(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ use aiken_lang::{ | |||
|         builder::{DataTypeKey, FunctionAccessKey}, | ||||
|         CodeGenerator, | ||||
|     }, | ||||
|     line_numbers::LineNumbers, | ||||
|     parser::extra::{comments_before, Comment, ModuleExtra}, | ||||
|     tipo::TypeInfo, | ||||
| }; | ||||
|  | @ -401,7 +402,10 @@ impl CheckedModules { | |||
|                     | Definition::Use(_) => {} | ||||
|                 } | ||||
|             } | ||||
|             module_src.insert(module.name.clone(), module.code.clone()); | ||||
|             module_src.insert( | ||||
|                 module.name.clone(), | ||||
|                 (module.code.clone(), LineNumbers::new(&module.code)), | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
|         let mut module_types_index = IndexMap::new(); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 KtorZ
						KtorZ