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