Compilation aided syntax highlighting

This commit is contained in:
Mia
2026-03-09 11:07:24 +01:00
parent 63890e46d9
commit dc94090976
11 changed files with 798 additions and 280 deletions
+2
View File
@@ -29,6 +29,8 @@ pub enum Code {
InvalidCast = 0x0207,
CannotDereference = 0x0209,
CannotInferType = 0x020A,
InvalidOperation = 0x020B,
InvalidParameterCount = 0x020C,
UninitializedField = 0x0300,
+3 -3
View File
@@ -1,15 +1,15 @@
use crate::{diagnostics::Diagnostic, metadata::CodePosition};
use crate::{diagnostics::Diagnostic, metadata::CodePath};
use leaf_assembly::values::AnyValue;
#[derive(Debug, Clone)]
pub enum Event<'l> {
Symbol {
value: AnyValue<'l>,
position: CodePosition,
position: CodePath,
},
Definition {
value: AnyValue<'l>,
position: CodePosition,
position: CodePath,
},
Diagnostic(Diagnostic),
}
+12
View File
@@ -32,3 +32,15 @@ impl CodePosition {
})
}
}
#[derive(Debug, Clone)]
pub struct CodePath {
pub file: Arc<SourceCode>,
pub path: Arc<[u32]>,
}
impl CodePath {
pub fn new(file: Arc<SourceCode>, path: Arc<[u32]>) -> Self {
Self { file, path }
}
}
+62 -29
View File
@@ -1,4 +1,9 @@
use crate::{CompilationContext, FuncQueue, diagnostics::*, events::Event, metadata::CodePosition};
use crate::{
CompilationContext, FuncQueue,
diagnostics::*,
events::Event,
metadata::{CodePath, CodePosition},
};
use arcstr::{Substr, literal_substr};
use leaf_assembly::{
assembly::Assembly,
@@ -16,6 +21,7 @@ use leaf_assembly::{
use leaf_parser::{
SourceCode,
ast::{self, *},
no_path,
};
use std::{
borrow::Cow,
@@ -80,8 +86,8 @@ impl<'l> Scope<'l> {
pub fn declare_constants(&mut self, decl: &[AstNode<ConstDecl>]) {
for val in decl {
for range in val.names.as_slice() {
let name = self.get_text_arc(range);
for name in val.names.as_slice() {
let name = self.get_text_arc(&name.range);
self.values.insert(
name,
Variable {
@@ -109,7 +115,7 @@ impl<'l> Scope<'l> {
)?;
match &*val.names {
NamePattern::Single(ident) => {
let name = self.get_text(ident).to_string();
let name = self.get_text(&ident.range).to_string();
self.values
.get_mut(&*name)
@@ -120,7 +126,7 @@ impl<'l> Scope<'l> {
self.ctx.emit_event(Event::Definition {
value: expr,
position: CodePosition::new(self.source.clone(), ident.clone()),
position: CodePath::new(self.source.clone(), ident.path.clone()),
});
}
NamePattern::Tuple(_) => todo!(),
@@ -161,6 +167,7 @@ impl<'l> Scope<'l> {
&AstNode {
range: block.range.clone(),
node: Expr::Block(block.clone()),
path: no_path(),
},
&func.ty.ret_t,
)?;
@@ -179,14 +186,14 @@ impl<'l> Scope<'l> {
ctx: &mut ExpressionContext<'l, '_>,
) -> Result<AnyValue<'l>, Diagnostic> {
match &**expr {
Expr::Ident(range) => {
let name = self.get_text(range);
Expr::Ident => {
let name = self.get_text(&expr.range);
match self.values.get(&*name) {
None => Err(Diagnostic {
kind: Kind::Error,
code: Code::SymbolNotFound,
message: format!("Symbol `{name}` does not exist in the current scope."),
position: CodePosition::new(self.source.clone(), range.clone()),
position: CodePosition::new(self.source.clone(), expr.range.clone()),
cause: None,
}),
Some(Variable { value, .. }) => match value.get() {
@@ -194,13 +201,13 @@ impl<'l> Scope<'l> {
kind: Kind::Error,
code: Code::UninitializedSymbol,
message: format!("Symbol `{name}` is not initialized at this time."),
position: CodePosition::new(self.source.clone(), range.clone()),
position: CodePosition::new(self.source.clone(), expr.range.clone()),
cause: None,
}),
Some(value) => {
self.ctx.emit_event(Event::Symbol {
value: *value,
position: CodePosition::new(self.source.clone(), range.clone()),
position: CodePath::new(self.source.clone(), expr.path.clone()),
});
Ok(*value)
}
@@ -241,7 +248,7 @@ impl<'l> Scope<'l> {
})
}};
}
let ty = n.ty.as_ref().map(|v| self.get_text(v));
let ty = n.ty.as_ref().map(|v| self.get_text(&v.range));
let value = match ty.as_ref().map(|ty| &**ty) {
None if ctx.type_hint == Some(Type::I8) => parse_number!(i8, I8),
None if ctx.type_hint == Some(Type::I16) => parse_number!(i16, I16),
@@ -273,13 +280,16 @@ impl<'l> Scope<'l> {
kind: Kind::Error,
code: Code::InvalidIntegerType,
message: format!("`{ty}` is not a valid integer type."),
position: CodePosition::new(self.source.clone(), n.ty.clone().unwrap()),
position: CodePosition::new(
self.source.clone(),
n.ty.clone().unwrap().range,
),
cause: None,
}),
}?;
self.ctx.emit_event(Event::Symbol {
value: value,
position: CodePosition::new(self.source.clone(), n.number.clone()),
position: CodePath::new(self.source.clone(), expr.path.clone()),
});
Ok(value)
}
@@ -290,7 +300,7 @@ impl<'l> Scope<'l> {
field,
} => {
let value = self.compile_expression(value_expr, ctx)?;
let name = self.get_text(field);
let name = self.get_text(&field.range);
if let Some(value) = value.get_associated_value(&*name) {
return Ok(value);
}
@@ -341,7 +351,7 @@ impl<'l> Scope<'l> {
if let Some(value) = value {
self.ctx.emit_event(Event::Symbol {
value: value,
position: CodePosition::new(self.source.clone(), field.clone()),
position: CodePath::new(self.source.clone(), field.path.clone()),
});
return Ok(value);
}
@@ -350,7 +360,7 @@ impl<'l> Scope<'l> {
kind: Kind::Error,
code: Code::FieldNotFound,
message: format!("Value does not contain field `{name}`."),
position: CodePosition::new(self.source.clone(), field.clone()),
position: CodePosition::new(self.source.clone(), field.range.clone()),
cause: None,
});
}
@@ -528,17 +538,20 @@ impl<'l> Scope<'l> {
_ => todo!("{src_ty} as {dst_ty}"),
}
}
(a, b, _) => todo!(
"{a} {op:?} {b} | {lhs:?} {op:?} {rhs:?}",
op = operator.node,
),
(a, b, _) => Err(Diagnostic {
kind: Kind::Error,
code: Code::InvalidOperation,
message: format!("Cannot perform operation between types `{a}` and `{b}`."),
position: CodePosition::new(self.source.clone(), expr.range.clone()),
cause: None,
}),
}
}
Expr::If(expr) => self.compile_if(expr, ctx),
Expr::While(expr) => {
let While { cond, block, .. } = &**expr;
let While { cond, block, .. } = &expr.node;
let mut builder = ctx.builder.as_mut().unwrap();
let cond_block = builder.create_block();
@@ -577,14 +590,32 @@ impl<'l> Scope<'l> {
});
}
};
if args_exprs.len() != func.ty.par_t.len() {
return Err(Diagnostic {
kind: Kind::Error,
code: Code::InvalidParameterCount,
message: format!(
"Expected {} parameters, found {}.",
func.ty.par_t.len(),
args_exprs.len()
),
position: CodePosition::new(self.source.clone(), expr.range.clone()),
cause: None,
});
}
let mut arg_ty = func.ty.par_t.iter().cloned();
let mut args = Vec::with_capacity(args_exprs.len());
for expr in args_exprs {
let expected = arg_ty.next();
let mut arg =
self.compile_expression(expr, &mut ctx.with_type_hit(arg_ty.next()))?;
self.compile_expression(expr, &mut ctx.with_type_hit(expected))?;
if arg.is_lvalue() {
arg = ctx.builder.as_mut().unwrap().load(arg).unwrap();
}
self.assert_ty_eq(&arg, expr, expected.as_ref().unwrap())?;
args.push(arg);
}
let builder = ctx.builder.as_mut().unwrap();
@@ -627,7 +658,7 @@ impl<'l> Scope<'l> {
},
Expr::Struct { fields, .. } => {
let name = match &ctx.decl_names {
Some(NamePattern::Single(func_name)) => &*self.get_text(func_name),
Some(NamePattern::Single(func_name)) => &*self.get_text(&func_name.range),
_ => "",
};
let struct_ty = self.assembly.create_struct(name);
@@ -651,10 +682,11 @@ impl<'l> Scope<'l> {
public,
mutable,
},
..
} in fields
{
let ty = scope.compile_expression(ty_expr, &mut expr_ctx)?;
let name = ctx.intern_str(&self.get_text(name));
let name = ctx.intern_str(&self.get_text(&name.range));
field_map.insert(
name,
Field {
@@ -852,7 +884,7 @@ impl<'l> Scope<'l> {
} in fields.values()
{
let Some(name_value_pair) = ctor_values.iter().find_map(|v| {
let name = self.get_text(&v.name);
let name = self.get_text(&v.name.range);
match name == *fld_name {
true => Some(&v.node),
false => None,
@@ -910,6 +942,7 @@ impl<'l> Scope<'l> {
let ast_as_expr = AstNode {
range: ast.range.clone(),
node: Expr::Func(ast.clone()),
path: no_path(),
};
let ret_ty = self.assert_ty(ret_ty, ast.ret.as_ref().unwrap_or(&ast_as_expr))?;
let mut par_ty = Vec::with_capacity(ast.args.len());
@@ -921,7 +954,7 @@ impl<'l> Scope<'l> {
let fn_ty = ret_ty.make_fn(par_ty);
let name = match &ctx.decl_names {
Some(NamePattern::Single(func_name)) => &*self.get_text(func_name),
Some(NamePattern::Single(func_name)) => &*self.get_text(&func_name.range),
_ => "",
};
let func = self.assembly.create_function(fn_ty, name);
@@ -931,7 +964,7 @@ impl<'l> Scope<'l> {
let mut scope = self.clone();
for (i, arg) in ast.args.iter().enumerate() {
let name = self.get_text_arc(&arg.name);
let name = self.get_text_arc(&arg.name.range);
scope.insert(name, AnyValue::Parameter(i, func));
}
@@ -965,7 +998,7 @@ impl<'l> Scope<'l> {
}
match names {
NamePattern::Single(ident) => {
let name = self.get_text_arc(ident);
let name = self.get_text_arc(&ident.range);
self.values.insert(
name,
Variable {
@@ -975,7 +1008,7 @@ impl<'l> Scope<'l> {
self.ctx.emit_event(Event::Definition {
value: value,
position: CodePosition::new(self.source.clone(), ident.clone()),
position: CodePath::new(self.source.clone(), ident.path.clone()),
});
}
NamePattern::Tuple(_) => todo!(),