Compilation aided syntax highlighting
This commit is contained in:
@@ -29,6 +29,8 @@ pub enum Code {
|
||||
InvalidCast = 0x0207,
|
||||
CannotDereference = 0x0209,
|
||||
CannotInferType = 0x020A,
|
||||
InvalidOperation = 0x020B,
|
||||
InvalidParameterCount = 0x020C,
|
||||
|
||||
UninitializedField = 0x0300,
|
||||
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
|
||||
@@ -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
@@ -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!(),
|
||||
|
||||
Reference in New Issue
Block a user