Incremental function compilation
This commit is contained in:
@@ -24,7 +24,6 @@ bitflags! {
|
|||||||
|
|
||||||
#[derive(Debug, Display, Clone, Copy, From, TryInto, PartialEq, Eq, Hash)]
|
#[derive(Debug, Display, Clone, Copy, From, TryInto, PartialEq, Eq, Hash)]
|
||||||
pub enum Value<'l> {
|
pub enum Value<'l> {
|
||||||
Uninit,
|
|
||||||
#[display("{_0}")]
|
#[display("{_0}")]
|
||||||
Constant(AnyConst<'l>),
|
Constant(AnyConst<'l>),
|
||||||
#[display("{_0}")]
|
#[display("{_0}")]
|
||||||
@@ -47,7 +46,6 @@ impl<'l> Value<'l> {
|
|||||||
Value::Constant(v) => v.ty(),
|
Value::Constant(v) => v.ty(),
|
||||||
Value::Instruction(v) => v.value_ty(),
|
Value::Instruction(v) => v.value_ty(),
|
||||||
Value::Parameter(i, f) => f.ty.par_t[*i],
|
Value::Parameter(i, f) => f.ty.par_t[*i],
|
||||||
Value::Uninit => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-3
@@ -3,17 +3,20 @@ use arcstr::literal_substr;
|
|||||||
use leaf_allocators::SyncAllocator;
|
use leaf_allocators::SyncAllocator;
|
||||||
use leaf_assembly::{
|
use leaf_assembly::{
|
||||||
assembly::{Assembly, AssemblyIdentifier, Context},
|
assembly::{Assembly, AssemblyIdentifier, Context},
|
||||||
|
functions::Function,
|
||||||
types::Type,
|
types::Type,
|
||||||
values::{AnyConst, Value},
|
values::{AnyConst, Value},
|
||||||
};
|
};
|
||||||
use leaf_parser::SourceCode;
|
use leaf_parser::{SourceCode, ast};
|
||||||
use std::{ops::Deref, sync::Arc};
|
use std::{collections::VecDeque, ops::Deref, sync::Arc};
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
mod scope;
|
mod scope;
|
||||||
|
|
||||||
pub type SourceFile = Arc<SourceCode>;
|
pub type SourceFile = Arc<SourceCode>;
|
||||||
|
|
||||||
|
type FuncQueue<'l> = VecDeque<(&'l Function<'l>, Arc<ast::Block>, Scope<'l>)>;
|
||||||
|
|
||||||
pub struct CompilationContext<'l> {
|
pub struct CompilationContext<'l> {
|
||||||
ctx: &'l Context<'l>,
|
ctx: &'l Context<'l>,
|
||||||
alloc: &'l dyn SyncAllocator,
|
alloc: &'l dyn SyncAllocator,
|
||||||
@@ -98,10 +101,16 @@ impl<'l> CompilationContext<'l> {
|
|||||||
scope.declare_constants(&unit.decls);
|
scope.declare_constants(&unit.decls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut queue = FuncQueue::new();
|
||||||
|
|
||||||
for i in 0..sources.len() {
|
for i in 0..sources.len() {
|
||||||
let unit = &units[i];
|
let unit = &units[i];
|
||||||
let scope = &mut scopes[i];
|
let scope = &mut scopes[i];
|
||||||
scope.define_constants(&unit.decls)?;
|
scope.define_constants(&unit.decls, &mut queue)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
while let Some((func, block, mut scope)) = queue.pop_back() {
|
||||||
|
scope.compile_function(func, &block, &mut queue)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
+90
-59
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::{FuncQueue, error::*};
|
||||||
use arcstr::Substr;
|
use arcstr::Substr;
|
||||||
use leaf_assembly::{
|
use leaf_assembly::{
|
||||||
assembly::Assembly,
|
assembly::Assembly,
|
||||||
@@ -12,19 +13,20 @@ use leaf_parser::{
|
|||||||
SourceCode,
|
SourceCode,
|
||||||
ast::{self, BinaryExpr, BinaryOp, ConstDecl, Expr, Ident, IndexingExpr, NamePattern, While},
|
ast::{self, BinaryExpr, BinaryOp, ConstDecl, Expr, Ident, IndexingExpr, NamePattern, While},
|
||||||
};
|
};
|
||||||
use std::{collections::HashMap, sync::Arc};
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
sync::{Arc, OnceLock},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::error::*;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
struct ExpressionContext<'l, 'r> {
|
struct ExpressionContext<'l, 'r> {
|
||||||
decl_names: Option<&'r NamePattern>,
|
decl_names: Option<&'r NamePattern>,
|
||||||
builder: Option<&'r mut FunctionBodyBuilder<'l>>,
|
builder: Option<&'r mut FunctionBodyBuilder<'l>>,
|
||||||
|
fn_queue: &'r mut FuncQueue<'l>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Variable<'l> {
|
struct Variable<'l> {
|
||||||
value: Value<'l>,
|
value: Arc<OnceLock<Value<'l>>>,
|
||||||
mutable: bool,
|
mutable: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +47,13 @@ impl<'l> Scope<'l> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, name: Substr, value: Value<'l>, mutable: bool) {
|
pub fn insert(&mut self, name: Substr, value: Value<'l>, mutable: bool) {
|
||||||
self.values.insert(name, Variable { value, mutable });
|
self.values.insert(
|
||||||
|
name,
|
||||||
|
Variable {
|
||||||
|
value: Arc::new(OnceLock::from(value)),
|
||||||
|
mutable,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn declare_constants(&mut self, decl: &[ConstDecl]) {
|
pub fn declare_constants(&mut self, decl: &[ConstDecl]) {
|
||||||
@@ -54,7 +62,7 @@ impl<'l> Scope<'l> {
|
|||||||
self.values.insert(
|
self.values.insert(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
Variable {
|
Variable {
|
||||||
value: Value::Uninit,
|
value: Arc::default(),
|
||||||
mutable: false,
|
mutable: false,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -62,19 +70,28 @@ impl<'l> Scope<'l> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn define_constants(&mut self, decl: &[ConstDecl]) -> Result<(), CompilationError> {
|
pub fn define_constants(
|
||||||
|
&mut self,
|
||||||
|
decl: &[ConstDecl],
|
||||||
|
fn_queue: &mut FuncQueue<'l>,
|
||||||
|
) -> Result<(), CompilationError> {
|
||||||
for val in decl {
|
for val in decl {
|
||||||
let expr = self.compile_expression(
|
let expr = self.compile_expression(
|
||||||
&val.value,
|
&val.value,
|
||||||
&mut ExpressionContext {
|
&mut ExpressionContext {
|
||||||
decl_names: Some(&val.names),
|
decl_names: Some(&val.names),
|
||||||
..Default::default()
|
builder: None,
|
||||||
|
fn_queue,
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
match &val.names {
|
match &val.names {
|
||||||
NamePattern::Single(ident) => {
|
NamePattern::Single(ident) => self
|
||||||
self.values.get_mut(&ident.0).unwrap().value = expr;
|
.values
|
||||||
}
|
.get_mut(&ident.0)
|
||||||
|
.unwrap()
|
||||||
|
.value
|
||||||
|
.set(expr)
|
||||||
|
.unwrap(),
|
||||||
NamePattern::Tuple(_) => todo!(),
|
NamePattern::Tuple(_) => todo!(),
|
||||||
NamePattern::List(_) => todo!(),
|
NamePattern::List(_) => todo!(),
|
||||||
}
|
}
|
||||||
@@ -82,6 +99,42 @@ impl<'l> Scope<'l> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn compile_function(
|
||||||
|
&mut self,
|
||||||
|
func: &'l Function<'l>,
|
||||||
|
block: &ast::Block,
|
||||||
|
fn_queue: &mut FuncQueue<'l>,
|
||||||
|
) -> Result<(), CompilationError> {
|
||||||
|
let mut builder = func.create_body().unwrap();
|
||||||
|
let mut ctx = ExpressionContext {
|
||||||
|
builder: Some(&mut builder),
|
||||||
|
decl_names: None,
|
||||||
|
fn_queue: fn_queue,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut last_expr = None;
|
||||||
|
for expr in &block.0 {
|
||||||
|
last_expr = Some(self.compile_expression(expr, &mut ctx)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !builder.current_block().has_termination() {
|
||||||
|
match func.ty.ret_t {
|
||||||
|
Type::Void => builder.ret(None).unwrap(),
|
||||||
|
_ => {
|
||||||
|
if let Some(expr) = last_expr.as_mut()
|
||||||
|
&& expr.flags().contains(ValueFlags::LValue)
|
||||||
|
{
|
||||||
|
*expr = builder.load(*expr).unwrap();
|
||||||
|
}
|
||||||
|
builder.ret(last_expr).unwrap()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.build().unwrap();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn compile_expression(
|
fn compile_expression(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
@@ -98,23 +151,22 @@ impl<'l> Scope<'l> {
|
|||||||
},
|
},
|
||||||
cause: None,
|
cause: None,
|
||||||
}),
|
}),
|
||||||
Some(Variable {
|
Some(Variable { value, .. }) => match value.get() {
|
||||||
value: Value::Uninit,
|
None => Err(CompilationError {
|
||||||
..
|
kind: Kind::UninitializedSymbol,
|
||||||
}) => Err(CompilationError {
|
message: format!("Symbol `{name}` is not initialized at this time."),
|
||||||
kind: Kind::UninitializedSymbol,
|
location: Location::Range {
|
||||||
message: format!("Symbol `{name}` is not initialized at this time."),
|
file: self.source.clone(),
|
||||||
location: Location::Range {
|
range: name.range(),
|
||||||
file: self.source.clone(),
|
},
|
||||||
range: name.range(),
|
cause: None,
|
||||||
},
|
}),
|
||||||
cause: None,
|
Some(value) => Ok(*value),
|
||||||
}),
|
},
|
||||||
Some(Variable { value, .. }) => Ok(*value),
|
|
||||||
},
|
},
|
||||||
|
|
||||||
Expr::Func(func) => self
|
Expr::Func(func) => self
|
||||||
.compile_function(func, ctx)
|
.make_function(func, ctx)
|
||||||
.map(|f| Value::Constant(AnyConst::Function(f)))
|
.map(|f| Value::Constant(AnyConst::Function(f)))
|
||||||
.map_err(|err| CompilationError {
|
.map_err(|err| CompilationError {
|
||||||
kind: Kind::FunctionCompilationFailed,
|
kind: Kind::FunctionCompilationFailed,
|
||||||
@@ -294,7 +346,8 @@ impl<'l> Scope<'l> {
|
|||||||
let mut scope = self.clone();
|
let mut scope = self.clone();
|
||||||
let mut ctx = ExpressionContext {
|
let mut ctx = ExpressionContext {
|
||||||
builder: Some(builder),
|
builder: Some(builder),
|
||||||
..Default::default()
|
decl_names: None,
|
||||||
|
fn_queue: ctx.fn_queue,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut last_expr = None;
|
let mut last_expr = None;
|
||||||
@@ -456,7 +509,7 @@ impl<'l> Scope<'l> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_function(
|
fn make_function(
|
||||||
&mut self,
|
&mut self,
|
||||||
ast: &ast::Function,
|
ast: &ast::Function,
|
||||||
ctx: &mut ExpressionContext<'l, '_>,
|
ctx: &mut ExpressionContext<'l, '_>,
|
||||||
@@ -477,9 +530,6 @@ impl<'l> Scope<'l> {
|
|||||||
let func = self.assembly.create_function(fn_ty);
|
let func = self.assembly.create_function(fn_ty);
|
||||||
if let Some(NamePattern::Single(func_name)) = &ctx.decl_names {
|
if let Some(NamePattern::Single(func_name)) = &ctx.decl_names {
|
||||||
func.name.set(func.ctx().intern_str(&func_name.0)).unwrap();
|
func.name.set(func.ctx().intern_str(&func_name.0)).unwrap();
|
||||||
if let Some(variable) = self.values.get_mut(func_name.as_str()) {
|
|
||||||
variable.value = Value::Constant(AnyConst::Function(func));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(block) = &ast.block else {
|
let Some(block) = &ast.block else {
|
||||||
@@ -491,32 +541,7 @@ impl<'l> Scope<'l> {
|
|||||||
scope.insert(arg.name.0.clone(), Value::Parameter(i, func), false);
|
scope.insert(arg.name.0.clone(), Value::Parameter(i, func), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut builder = func.create_body().unwrap();
|
ctx.fn_queue.push_back((func, block.clone(), scope));
|
||||||
let mut ctx = ExpressionContext {
|
|
||||||
builder: Some(&mut builder),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut last_expr = None;
|
|
||||||
for expr in &block.0 {
|
|
||||||
last_expr = Some(scope.compile_expression(expr, &mut ctx)?);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !builder.current_block().has_termination() {
|
|
||||||
match func.ty.ret_t {
|
|
||||||
Type::Void => builder.ret(None).unwrap(),
|
|
||||||
_ => {
|
|
||||||
if let Some(expr) = last_expr.as_mut()
|
|
||||||
&& expr.flags().contains(ValueFlags::LValue)
|
|
||||||
{
|
|
||||||
*expr = builder.load(*expr).unwrap();
|
|
||||||
}
|
|
||||||
builder.ret(last_expr).unwrap()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.build().unwrap();
|
|
||||||
|
|
||||||
Ok(func)
|
Ok(func)
|
||||||
}
|
}
|
||||||
@@ -531,6 +556,7 @@ impl<'l> Scope<'l> {
|
|||||||
let mut sub_ctx = ExpressionContext {
|
let mut sub_ctx = ExpressionContext {
|
||||||
decl_names: Some(names),
|
decl_names: Some(names),
|
||||||
builder: ctx.builder.as_deref_mut(),
|
builder: ctx.builder.as_deref_mut(),
|
||||||
|
fn_queue: ctx.fn_queue,
|
||||||
};
|
};
|
||||||
let mut value = self.compile_expression(value, &mut sub_ctx)?;
|
let mut value = self.compile_expression(value, &mut sub_ctx)?;
|
||||||
if mutable {
|
if mutable {
|
||||||
@@ -541,8 +567,13 @@ impl<'l> Scope<'l> {
|
|||||||
}
|
}
|
||||||
match names {
|
match names {
|
||||||
NamePattern::Single(ident) => {
|
NamePattern::Single(ident) => {
|
||||||
self.values
|
self.values.insert(
|
||||||
.insert(ident.0.clone(), Variable { value, mutable });
|
ident.0.clone(),
|
||||||
|
Variable {
|
||||||
|
value: Arc::new(OnceLock::from(value)),
|
||||||
|
mutable,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
NamePattern::Tuple(_) => todo!(),
|
NamePattern::Tuple(_) => todo!(),
|
||||||
NamePattern::List(_) => todo!(),
|
NamePattern::List(_) => todo!(),
|
||||||
|
|||||||
+13
-13
@@ -1,7 +1,7 @@
|
|||||||
use std::ops::Range;
|
|
||||||
|
|
||||||
use arcstr::Substr;
|
use arcstr::Substr;
|
||||||
use derive_more::Deref;
|
use derive_more::Deref;
|
||||||
|
use std::ops::Range;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Debug, Deref)]
|
#[derive(Debug, Deref)]
|
||||||
pub struct Ident(pub Substr);
|
pub struct Ident(pub Substr);
|
||||||
@@ -25,29 +25,29 @@ pub enum Expr {
|
|||||||
Number(Number),
|
Number(Number),
|
||||||
String(Substr),
|
String(Substr),
|
||||||
#[debug("{_0:?}")]
|
#[debug("{_0:?}")]
|
||||||
Binary(Box<BinaryExpr>),
|
Binary(Arc<BinaryExpr>),
|
||||||
Index(Box<IndexingExpr>),
|
Index(Arc<IndexingExpr>),
|
||||||
Tuple(Vec<Expr>),
|
Tuple(Vec<Expr>),
|
||||||
List(Vec<Expr>),
|
List(Vec<Expr>),
|
||||||
Struct(Box<StructCtor>),
|
Struct(Arc<StructCtor>),
|
||||||
#[debug("{_0:?}")]
|
#[debug("{_0:?}")]
|
||||||
Block(Block),
|
Block(Block),
|
||||||
#[debug("{_0:?}")]
|
#[debug("{_0:?}")]
|
||||||
Func(Box<Function>),
|
Func(Arc<Function>),
|
||||||
#[debug("{_0:?}")]
|
#[debug("{_0:?}")]
|
||||||
Type(Box<Type>),
|
Type(Arc<Type>),
|
||||||
|
|
||||||
#[debug("{_0:?}")]
|
#[debug("{_0:?}")]
|
||||||
ConstDecl(Box<ConstDecl>),
|
ConstDecl(Arc<ConstDecl>),
|
||||||
#[debug("{_0:?}")]
|
#[debug("{_0:?}")]
|
||||||
VarDecl(Box<VarDecl>),
|
VarDecl(Arc<VarDecl>),
|
||||||
#[debug("{_0:?}")]
|
#[debug("{_0:?}")]
|
||||||
For(Box<For>),
|
For(Arc<For>),
|
||||||
#[debug("{_0:?}")]
|
#[debug("{_0:?}")]
|
||||||
While(Box<While>),
|
While(Arc<While>),
|
||||||
|
|
||||||
Call {
|
Call {
|
||||||
func: Box<Expr>,
|
func: Arc<Expr>,
|
||||||
args: Vec<Expr>,
|
args: Vec<Expr>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,7 @@ pub struct Function {
|
|||||||
pub text: Substr,
|
pub text: Substr,
|
||||||
pub args: Vec<NameValuePair>,
|
pub args: Vec<NameValuePair>,
|
||||||
pub ret: Option<Expr>,
|
pub ret: Option<Expr>,
|
||||||
pub block: Option<Block>,
|
pub block: Option<Arc<Block>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|||||||
+26
-25
@@ -3,6 +3,7 @@ use crate::ast::*;
|
|||||||
use arcstr::Substr;
|
use arcstr::Substr;
|
||||||
use peg::{Parse, ParseElem, ParseLiteral, ParseSlice};
|
use peg::{Parse, ParseElem, ParseLiteral, ParseSlice};
|
||||||
pub use peg::{error::*, str::LineCol};
|
pub use peg::{error::*, str::LineCol};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
impl Parse for SourceCode {
|
impl Parse for SourceCode {
|
||||||
type PositionRepr = LineCol;
|
type PositionRepr = LineCol;
|
||||||
@@ -69,40 +70,40 @@ peg::parser! {
|
|||||||
// ### EXPRESSIONS ####
|
// ### EXPRESSIONS ####
|
||||||
|
|
||||||
rule expr() -> Expr = precedence! {
|
rule expr() -> Expr = precedence! {
|
||||||
lhs:(@) __ op:$("as") __ rhs:@ { Expr::Binary(Box::new(BinaryExpr { lhs, op: BinaryOp::Cast(op), rhs })) }
|
lhs:(@) __ op:$("as") __ rhs:@ { Expr::Binary(Arc::new(BinaryExpr { lhs, op: BinaryOp::Cast(op), rhs })) }
|
||||||
--
|
--
|
||||||
lhs:@ __ op:$("=") __ rhs:expr() { Expr::Binary(Box::new(BinaryExpr { lhs, op: BinaryOp::Assign(op), rhs })) }
|
lhs:@ __ op:$("=") __ rhs:expr() { Expr::Binary(Arc::new(BinaryExpr { lhs, op: BinaryOp::Assign(op), rhs })) }
|
||||||
lhs:(@) __ op:$(".") __ rhs:@ { Expr::Binary(Box::new(BinaryExpr { lhs, op: BinaryOp::Dot(op), rhs })) }
|
lhs:(@) __ op:$(".") __ rhs:@ { Expr::Binary(Arc::new(BinaryExpr { lhs, op: BinaryOp::Dot(op), rhs })) }
|
||||||
lhs:(@) "(" __ args:(expr() ** ("," __)) __ ")" { Expr::Call { func: Box::new(lhs), args } }
|
lhs:(@) "(" __ args:(expr() ** ("," __)) __ ")" { Expr::Call { func: Arc::new(lhs), args } }
|
||||||
value:(@) "[" __ index:expr() __ "]" { Expr::Index(Box::new(IndexingExpr { value, index })) }
|
value:(@) "[" __ index:expr() __ "]" { Expr::Index(Arc::new(IndexingExpr { value, index })) }
|
||||||
r#type:(@) _ "{" __ values:name_value_pairs() __ "}" { Expr::Struct(Box::new(StructCtor { r#type, values })) }
|
r#type:(@) _ "{" __ values:name_value_pairs() __ "}" { Expr::Struct(Arc::new(StructCtor { r#type, values })) }
|
||||||
--
|
--
|
||||||
lhs:(@) __ op:$("+") __ rhs:@ { Expr::Binary(Box::new(BinaryExpr { lhs, op: BinaryOp::Add(op), rhs })) }
|
lhs:(@) __ op:$("+") __ rhs:@ { Expr::Binary(Arc::new(BinaryExpr { lhs, op: BinaryOp::Add(op), rhs })) }
|
||||||
lhs:(@) __ op:$("-") __ rhs:@ { Expr::Binary(Box::new(BinaryExpr { lhs, op: BinaryOp::Sub(op), rhs })) }
|
lhs:(@) __ op:$("-") __ rhs:@ { Expr::Binary(Arc::new(BinaryExpr { lhs, op: BinaryOp::Sub(op), rhs })) }
|
||||||
--
|
--
|
||||||
lhs:(@) __ op:$("*") __ rhs:@ { Expr::Binary(Box::new(BinaryExpr { lhs, op: BinaryOp::Mul(op), rhs })) }
|
lhs:(@) __ op:$("*") __ rhs:@ { Expr::Binary(Arc::new(BinaryExpr { lhs, op: BinaryOp::Mul(op), rhs })) }
|
||||||
lhs:(@) __ op:$("/") __ rhs:@ { Expr::Binary(Box::new(BinaryExpr { lhs, op: BinaryOp::Div(op), rhs })) }
|
lhs:(@) __ op:$("/") __ rhs:@ { Expr::Binary(Arc::new(BinaryExpr { lhs, op: BinaryOp::Div(op), rhs })) }
|
||||||
lhs:(@) __ op:$("%") __ rhs:@ { Expr::Binary(Box::new(BinaryExpr { lhs, op: BinaryOp::Mod(op), rhs })) }
|
lhs:(@) __ op:$("%") __ rhs:@ { Expr::Binary(Arc::new(BinaryExpr { lhs, op: BinaryOp::Mod(op), rhs })) }
|
||||||
--
|
--
|
||||||
lhs:(@) __ op:$("..") __ rhs:@ { Expr::Binary(Box::new(BinaryExpr { lhs, op: BinaryOp::Range(op), rhs })) }
|
lhs:(@) __ op:$("..") __ rhs:@ { Expr::Binary(Arc::new(BinaryExpr { lhs, op: BinaryOp::Range(op), rhs })) }
|
||||||
--
|
--
|
||||||
lhs:(@) __ op:$("==") __ rhs:@ { Expr::Binary(Box::new(BinaryExpr { lhs, op: BinaryOp::Eq(op), rhs })) }
|
lhs:(@) __ op:$("==") __ rhs:@ { Expr::Binary(Arc::new(BinaryExpr { lhs, op: BinaryOp::Eq(op), rhs })) }
|
||||||
lhs:(@) __ op:$("!=") __ rhs:@ { Expr::Binary(Box::new(BinaryExpr { lhs, op: BinaryOp::Ne(op), rhs })) }
|
lhs:(@) __ op:$("!=") __ rhs:@ { Expr::Binary(Arc::new(BinaryExpr { lhs, op: BinaryOp::Ne(op), rhs })) }
|
||||||
lhs:(@) __ op:$("<") __ rhs:@ { Expr::Binary(Box::new(BinaryExpr { lhs, op: BinaryOp::Lt(op), rhs })) }
|
lhs:(@) __ op:$("<") __ rhs:@ { Expr::Binary(Arc::new(BinaryExpr { lhs, op: BinaryOp::Lt(op), rhs })) }
|
||||||
lhs:(@) __ op:$(">") __ rhs:@ { Expr::Binary(Box::new(BinaryExpr { lhs, op: BinaryOp::Gt(op), rhs })) }
|
lhs:(@) __ op:$(">") __ rhs:@ { Expr::Binary(Arc::new(BinaryExpr { lhs, op: BinaryOp::Gt(op), rhs })) }
|
||||||
lhs:(@) __ op:$("<=") __ rhs:@ { Expr::Binary(Box::new(BinaryExpr { lhs, op: BinaryOp::Le(op), rhs })) }
|
lhs:(@) __ op:$("<=") __ rhs:@ { Expr::Binary(Arc::new(BinaryExpr { lhs, op: BinaryOp::Le(op), rhs })) }
|
||||||
lhs:(@) __ op:$(">=") __ rhs:@ { Expr::Binary(Box::new(BinaryExpr { lhs, op: BinaryOp::Ge(op), rhs })) }
|
lhs:(@) __ op:$(">=") __ rhs:@ { Expr::Binary(Arc::new(BinaryExpr { lhs, op: BinaryOp::Ge(op), rhs })) }
|
||||||
--
|
--
|
||||||
block:block() { Expr::Block(block)}
|
block:block() { Expr::Block(block)}
|
||||||
for_loop:for_loop() { Expr::For(Box::new(for_loop))}
|
for_loop:for_loop() { Expr::For(Arc::new(for_loop))}
|
||||||
while_loop:while_loop() { Expr::While(Box::new(while_loop))}
|
while_loop:while_loop() { Expr::While(Arc::new(while_loop))}
|
||||||
func:func() { Expr::Func(Box::new(func))}
|
func:func() { Expr::Func(Arc::new(func))}
|
||||||
var_decl:var_decl() { Expr::VarDecl(Box::new(var_decl)) }
|
var_decl:var_decl() { Expr::VarDecl(Arc::new(var_decl)) }
|
||||||
const_decl:const_decl() { Expr::ConstDecl(Box::new(const_decl)) }
|
const_decl:const_decl() { Expr::ConstDecl(Arc::new(const_decl)) }
|
||||||
"(" __ tuple:(expr() **<2,> ("," __)) __ ")" { Expr::Tuple(tuple) }
|
"(" __ tuple:(expr() **<2,> ("," __)) __ ")" { Expr::Tuple(tuple) }
|
||||||
"[" __ list:(expr() ** ("," __)) __ "]" { Expr::List(list) }
|
"[" __ list:(expr() ** ("," __)) __ "]" { Expr::List(list) }
|
||||||
"(" __ v:expr() __ ")" { v }
|
"(" __ v:expr() __ ")" { v }
|
||||||
"*" __ m:"mut"? __ v:expr() { Expr::Type(Box::new(Type::Ptr { base:v, mutable: m.is_some() })) }
|
"*" __ m:"mut"? __ v:expr() { Expr::Type(Arc::new(Type::Ptr { base:v, mutable: m.is_some() })) }
|
||||||
v:string() { Expr::String(v) }
|
v:string() { Expr::String(v) }
|
||||||
v:number() { Expr::Number(v) }
|
v:number() { Expr::Number(v) }
|
||||||
v:ident() { Expr::Ident(v) }
|
v:ident() { Expr::Ident(v) }
|
||||||
@@ -113,7 +114,7 @@ peg::parser! {
|
|||||||
|
|
||||||
rule func() -> Function
|
rule func() -> Function
|
||||||
= s:position!() t:$"fn" __ "(" __ args:name_value_pairs() __ ")" __ ret:("->" __ e:expr() {e})? __ block:block()? e:position!()
|
= s:position!() t:$"fn" __ "(" __ args:name_value_pairs() __ ")" __ ret:("->" __ e:expr() {e})? __ block:block()? e:position!()
|
||||||
{ Function { args, ret, block, text: t.parent().substr(s..e), } }
|
{ Function { args, ret, block: block.map(Arc::new), text: t.parent().substr(s..e), } }
|
||||||
|
|
||||||
rule name_value_pair() -> NameValuePair
|
rule name_value_pair() -> NameValuePair
|
||||||
= name:ident() __ ":" __ r#type:expr() { NameValuePair { name, r#type } }
|
= name:ident() __ ":" __ r#type:expr() { NameValuePair { name, r#type } }
|
||||||
|
|||||||
Reference in New Issue
Block a user