mirror of
https://github.com/edg-l/edlang.git
synced 2024-11-09 09:38:24 +00:00
feat: compile unary op, compile asref, compile deref, reference arguments, avoid some temporaries on direct use
This commit is contained in:
parent
6d31a9ea6f
commit
819a70d9f5
|
@ -31,20 +31,6 @@ pub struct PathExpr {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PathExpr {
|
|
||||||
pub fn get_full_path(&self) -> String {
|
|
||||||
let mut result = self.first.name.clone();
|
|
||||||
for path in &self.extra {
|
|
||||||
result.push('.');
|
|
||||||
match path {
|
|
||||||
PathSegment::Field(name) => result.push_str(&name.name),
|
|
||||||
PathSegment::Index { .. } => result.push_str("[]"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub enum PathSegment {
|
pub enum PathSegment {
|
||||||
Field(Ident),
|
Field(Ident),
|
||||||
|
@ -109,6 +95,7 @@ pub struct LetStmt {
|
||||||
pub struct AssignStmt {
|
pub struct AssignStmt {
|
||||||
pub name: PathExpr,
|
pub name: PathExpr,
|
||||||
pub value: Expression,
|
pub value: Expression,
|
||||||
|
pub deref_times: usize,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,6 +169,8 @@ pub enum Expression {
|
||||||
FnCall(FnCallExpr),
|
FnCall(FnCallExpr),
|
||||||
Unary(UnaryOp, Box<Self>),
|
Unary(UnaryOp, Box<Self>),
|
||||||
Binary(Box<Self>, BinaryOp, Box<Self>),
|
Binary(Box<Self>, BinaryOp, Box<Self>),
|
||||||
|
Deref(Box<Self>),
|
||||||
|
AsRef(Box<Self>, bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
|
|
@ -18,7 +18,7 @@ use inkwell::{
|
||||||
AddressSpace,
|
AddressSpace,
|
||||||
};
|
};
|
||||||
use ir::{LocalKind, ModuleBody, ProgramBody, TypeInfo, ValueTree};
|
use ir::{LocalKind, ModuleBody, ProgramBody, TypeInfo, ValueTree};
|
||||||
use llvm_sys::debuginfo::{LLVMDIFlagLValueReference, LLVMDIFlagPublic};
|
use llvm_sys::debuginfo::LLVMDIFlagPublic;
|
||||||
use tracing::{info, trace};
|
use tracing::{info, trace};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
@ -234,40 +234,7 @@ fn compile_fn_signature(ctx: &ModuleCompileCtx<'_, '_>, fn_id: DefId) {
|
||||||
|
|
||||||
// https://llvm.org/doxygen/group__LLVMCCoreTypes.html
|
// https://llvm.org/doxygen/group__LLVMCCoreTypes.html
|
||||||
|
|
||||||
/* starting from 1 to 80
|
fn_value.set_call_conventions(0); // cconv
|
||||||
allocalign allocptr alwaysinline builtin cold convergent disable_sanitizer_instrumentation fn_ret_thunk_extern hot
|
|
||||||
immarg inreg inlinehint jumptable minsize mustprogress naked nest noalias
|
|
||||||
nobuiltin nocallback nocapture nocf_check noduplicate nofree noimplicitfloat
|
|
||||||
noinline nomerge noprofile norecurse noredzone noreturn nosanitize_bounds
|
|
||||||
nosanitize_coverage nosync noundef nounwind nonlazybind nonnull null_pointer_is_valid
|
|
||||||
optforfuzzing optsize optnone presplitcoroutine readnone readonly returned returns_twice
|
|
||||||
signext safestack sanitize_address sanitize_hwaddress sanitize_memtag sanitize_memory
|
|
||||||
sanitize_thread shadowcallstack skipprofile speculatable speculative_load_hardening ssp
|
|
||||||
sspreq sspstrong strictfp swiftasync swifterror swiftself willreturn writeonly (67) zeroext byref byval elementtype inalloca
|
|
||||||
preallocated sret align 0 allockind(\"\") allocsize(0,0) dereferenceable(0) dereferenceable_or_null(0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
// nounwind
|
|
||||||
fn_value.add_attribute(
|
|
||||||
inkwell::attributes::AttributeLoc::Function,
|
|
||||||
ctx.ctx.context.create_enum_attribute(36, 0),
|
|
||||||
);
|
|
||||||
|
|
||||||
// nonlazybind
|
|
||||||
fn_value.add_attribute(
|
|
||||||
inkwell::attributes::AttributeLoc::Function,
|
|
||||||
ctx.ctx.context.create_enum_attribute(37, 0),
|
|
||||||
);
|
|
||||||
|
|
||||||
// willreturn
|
|
||||||
fn_value.add_attribute(
|
|
||||||
inkwell::attributes::AttributeLoc::Function,
|
|
||||||
ctx.ctx.context.create_enum_attribute(66, 0),
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
|
|
||||||
fn_value.set_call_conventions(0);
|
|
||||||
|
|
||||||
let (_, line, _col) = ctx
|
let (_, line, _col) = ctx
|
||||||
.ctx
|
.ctx
|
||||||
|
@ -420,11 +387,29 @@ fn compile_fn(ctx: &ModuleCompileCtx, fn_id: DefId) -> Result<(), BuilderError>
|
||||||
match &stmt.kind {
|
match &stmt.kind {
|
||||||
ir::StatementKind::Assign(place, rvalue) => {
|
ir::StatementKind::Assign(place, rvalue) => {
|
||||||
let local = &body.locals[place.local];
|
let local = &body.locals[place.local];
|
||||||
|
let mut local_ty = local.ty.clone();
|
||||||
|
let mut ptr = *locals.get(&place.local).unwrap();
|
||||||
|
|
||||||
|
for proj in &place.projection {
|
||||||
|
match proj {
|
||||||
|
ir::PlaceElem::Deref => {
|
||||||
|
ptr = ctx
|
||||||
|
.builder
|
||||||
|
.build_load(compile_basic_type(ctx, &local_ty), ptr, "deref")?
|
||||||
|
.into_pointer_value();
|
||||||
|
local_ty = match local_ty.kind {
|
||||||
|
ir::TypeKind::Ptr(inner) => *inner,
|
||||||
|
ir::TypeKind::Ref(_, inner) => *inner,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ir::PlaceElem::Field { .. } => todo!(),
|
||||||
|
ir::PlaceElem::Index { .. } => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let (value, _value_ty) = compile_rvalue(ctx, fn_id, &locals, rvalue)?;
|
let (value, _value_ty) = compile_rvalue(ctx, fn_id, &locals, rvalue)?;
|
||||||
let instruction = ctx
|
let instruction = ctx.builder.build_store(ptr, value)?;
|
||||||
.builder
|
|
||||||
.build_store(*locals.get(&place.local).unwrap(), value)?;
|
|
||||||
|
|
||||||
if let Some(_debug_name) = &local.debug_name {
|
if let Some(_debug_name) = &local.debug_name {
|
||||||
let di_local = di_locals.get(&place.local).unwrap();
|
let di_local = di_locals.get(&place.local).unwrap();
|
||||||
|
@ -558,6 +543,41 @@ fn compile_fn(ctx: &ModuleCompileCtx, fn_id: DefId) -> Result<(), BuilderError>
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn compile_unary_op<'ctx>(
|
||||||
|
ctx: &ModuleCompileCtx<'ctx, '_>,
|
||||||
|
fn_id: DefId,
|
||||||
|
locals: &HashMap<usize, PointerValue<'ctx>>,
|
||||||
|
op: ir::UnOp,
|
||||||
|
value: &ir::Operand,
|
||||||
|
) -> Result<(BasicValueEnum<'ctx>, TypeInfo), BuilderError> {
|
||||||
|
let (value, ty) = compile_load_operand(ctx, fn_id, locals, value)?;
|
||||||
|
|
||||||
|
let is_float = matches!(ty.kind, ir::TypeKind::Float(_));
|
||||||
|
|
||||||
|
Ok(match op {
|
||||||
|
ir::UnOp::Not => {
|
||||||
|
assert!(ty.kind.is_integer(), "must be a integer");
|
||||||
|
let value = ctx
|
||||||
|
.builder
|
||||||
|
.build_not(value.into_int_value(), "not")?
|
||||||
|
.as_basic_value_enum();
|
||||||
|
(value, ty)
|
||||||
|
}
|
||||||
|
ir::UnOp::Neg => {
|
||||||
|
let value = if is_float {
|
||||||
|
ctx.builder
|
||||||
|
.build_float_neg(value.into_float_value(), "negf")?
|
||||||
|
.as_basic_value_enum()
|
||||||
|
} else {
|
||||||
|
ctx.builder
|
||||||
|
.build_int_neg(value.into_int_value(), "negi")?
|
||||||
|
.as_basic_value_enum()
|
||||||
|
};
|
||||||
|
(value, ty)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn compile_bin_op<'ctx>(
|
fn compile_bin_op<'ctx>(
|
||||||
ctx: &ModuleCompileCtx<'ctx, '_>,
|
ctx: &ModuleCompileCtx<'ctx, '_>,
|
||||||
fn_id: DefId,
|
fn_id: DefId,
|
||||||
|
@ -908,10 +928,40 @@ fn compile_rvalue<'ctx>(
|
||||||
) -> Result<(BasicValueEnum<'ctx>, TypeInfo), BuilderError> {
|
) -> Result<(BasicValueEnum<'ctx>, TypeInfo), BuilderError> {
|
||||||
Ok(match rvalue {
|
Ok(match rvalue {
|
||||||
ir::RValue::Use(op) => compile_load_operand(ctx, fn_id, locals, op)?,
|
ir::RValue::Use(op) => compile_load_operand(ctx, fn_id, locals, op)?,
|
||||||
ir::RValue::Ref(_, _) => todo!(),
|
ir::RValue::Ref(_mutable, op) => match op {
|
||||||
|
ir::Operand::Copy(_) => todo!(),
|
||||||
|
ir::Operand::Move(place) => {
|
||||||
|
let mut ptr = *locals.get(&place.local).unwrap();
|
||||||
|
let mut local_ty = {
|
||||||
|
let body = ctx.ctx.program.functions.get(&fn_id).unwrap();
|
||||||
|
body.locals[place.local].ty.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
for proj in &place.projection {
|
||||||
|
match proj {
|
||||||
|
ir::PlaceElem::Deref => {
|
||||||
|
ptr = ctx
|
||||||
|
.builder
|
||||||
|
.build_load(compile_basic_type(ctx, &local_ty), ptr, "deref")?
|
||||||
|
.into_pointer_value();
|
||||||
|
local_ty = match local_ty.kind {
|
||||||
|
ir::TypeKind::Ptr(inner) => *inner,
|
||||||
|
ir::TypeKind::Ref(_, inner) => *inner,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ir::PlaceElem::Field { .. } => todo!(),
|
||||||
|
ir::PlaceElem::Index { .. } => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(ptr.as_basic_value_enum(), local_ty)
|
||||||
|
}
|
||||||
|
ir::Operand::Constant(_) => todo!("references to constants not yet implemented"),
|
||||||
|
},
|
||||||
ir::RValue::BinOp(op, lhs, rhs) => compile_bin_op(ctx, fn_id, locals, *op, lhs, rhs)?,
|
ir::RValue::BinOp(op, lhs, rhs) => compile_bin_op(ctx, fn_id, locals, *op, lhs, rhs)?,
|
||||||
ir::RValue::LogicOp(_, _, _) => todo!(),
|
ir::RValue::LogicOp(_, _, _) => todo!(),
|
||||||
ir::RValue::UnOp(_, _) => todo!(),
|
ir::RValue::UnOp(op, value) => compile_unary_op(ctx, fn_id, locals, *op, value)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -933,8 +983,29 @@ fn compile_load_operand<'ctx>(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ir::Operand::Move(place) => {
|
ir::Operand::Move(place) => {
|
||||||
let pointee_ty = compile_basic_type(ctx, &body.locals[place.local].ty);
|
let mut ptr = *locals.get(&place.local).unwrap();
|
||||||
let ptr = *locals.get(&place.local).unwrap();
|
let mut local_ty = body.locals[place.local].ty.clone();
|
||||||
|
|
||||||
|
for proj in &place.projection {
|
||||||
|
match proj {
|
||||||
|
ir::PlaceElem::Deref => {
|
||||||
|
ptr = ctx
|
||||||
|
.builder
|
||||||
|
.build_load(compile_basic_type(ctx, &local_ty), ptr, "deref")?
|
||||||
|
.into_pointer_value();
|
||||||
|
local_ty = match local_ty.kind {
|
||||||
|
ir::TypeKind::Ptr(inner) => *inner,
|
||||||
|
ir::TypeKind::Ref(_, inner) => *inner,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ir::PlaceElem::Field { .. } => todo!(),
|
||||||
|
ir::PlaceElem::Index { .. } => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let pointee_ty = compile_basic_type(ctx, &local_ty);
|
||||||
|
|
||||||
(
|
(
|
||||||
ctx.builder.build_load(pointee_ty, ptr, "")?,
|
ctx.builder.build_load(pointee_ty, ptr, "")?,
|
||||||
body.locals[place.local].ty.clone(),
|
body.locals[place.local].ty.clone(),
|
||||||
|
|
|
@ -208,10 +208,14 @@ pub enum TypeKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeKind {
|
impl TypeKind {
|
||||||
pub fn is_unit(&self) -> bool {
|
pub const fn is_unit(&self) -> bool {
|
||||||
matches!(self, Self::Unit)
|
matches!(self, Self::Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn is_integer(&self) -> bool {
|
||||||
|
matches!(self, Self::Int(_) | Self::Uint(_))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_falsy_value(&self) -> ValueTree {
|
pub fn get_falsy_value(&self) -> ValueTree {
|
||||||
match self {
|
match self {
|
||||||
Self::Bool => ValueTree::Leaf(ConstValue::Bool(false)),
|
Self::Bool => ValueTree::Leaf(ConstValue::Bool(false)),
|
||||||
|
|
|
@ -5,8 +5,8 @@ use common::{BodyBuilder, BuildCtx};
|
||||||
use edlang_ast as ast;
|
use edlang_ast as ast;
|
||||||
use edlang_ir as ir;
|
use edlang_ir as ir;
|
||||||
use ir::{
|
use ir::{
|
||||||
BasicBlock, Body, DefId, Local, LocalKind, Operand, Place, ProgramBody, Statement,
|
BasicBlock, Body, DefId, Local, LocalKind, Operand, Place, PlaceElem, ProgramBody, RValue,
|
||||||
StatementKind, SwitchTarget, Terminator, TypeInfo, TypeKind,
|
Statement, StatementKind, SwitchTarget, Terminator, TypeInfo, TypeKind,
|
||||||
};
|
};
|
||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
|
|
||||||
|
@ -371,10 +371,40 @@ fn lower_let(builder: &mut BodyBuilder, info: &ast::LetStmt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_assign(builder: &mut BodyBuilder, info: &ast::AssignStmt) {
|
fn lower_assign(builder: &mut BodyBuilder, info: &ast::AssignStmt) {
|
||||||
let local = *builder.name_to_local.get(&info.name.first.name).unwrap();
|
let (mut place, mut ty) = lower_path(builder, &info.name);
|
||||||
let ty = builder.body.locals[local].ty.clone();
|
|
||||||
let (rvalue, _ty) = lower_expr(builder, &info.value, Some(&ty.kind));
|
if let Some(PlaceElem::Deref) = place.projection.last() {
|
||||||
let (place, _ty) = lower_path(builder, &info.name);
|
match &ty {
|
||||||
|
TypeKind::Ptr(inner) => {
|
||||||
|
ty = inner.kind.clone();
|
||||||
|
}
|
||||||
|
TypeKind::Ref(is_mut, inner) => {
|
||||||
|
if !is_mut {
|
||||||
|
panic!("trying to mutate non mut ref");
|
||||||
|
}
|
||||||
|
ty = inner.kind.clone();
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _ in 0..info.deref_times {
|
||||||
|
match &ty {
|
||||||
|
TypeKind::Ptr(inner) => {
|
||||||
|
ty = inner.kind.clone();
|
||||||
|
}
|
||||||
|
TypeKind::Ref(is_mut, inner) => {
|
||||||
|
if !is_mut {
|
||||||
|
panic!("trying to mutate non mut ref");
|
||||||
|
}
|
||||||
|
ty = inner.kind.clone();
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
place.projection.push(PlaceElem::Deref);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (rvalue, _ty) = lower_expr(builder, &info.value, Some(&ty));
|
||||||
|
|
||||||
builder.statements.push(Statement {
|
builder.statements.push(Statement {
|
||||||
span: Some(info.name.first.span),
|
span: Some(info.name.first.span),
|
||||||
|
@ -426,6 +456,8 @@ fn find_expr_type(builder: &mut BodyBuilder, info: &ast::Expression) -> Option<T
|
||||||
find_expr_type(builder, lhs).or(find_expr_type(builder, rhs))?
|
find_expr_type(builder, lhs).or(find_expr_type(builder, rhs))?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ast::Expression::Deref(_) => todo!(),
|
||||||
|
ast::Expression::AsRef(_, _) => todo!(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,6 +479,50 @@ fn lower_expr(
|
||||||
ast::Expression::Binary(lhs, op, rhs) => {
|
ast::Expression::Binary(lhs, op, rhs) => {
|
||||||
lower_binary_expr(builder, lhs, op, rhs, type_hint)
|
lower_binary_expr(builder, lhs, op, rhs, type_hint)
|
||||||
}
|
}
|
||||||
|
ast::Expression::Deref(_) => todo!(),
|
||||||
|
ast::Expression::AsRef(inner, mutable) => {
|
||||||
|
let type_hint = match type_hint {
|
||||||
|
Some(inner) => match inner {
|
||||||
|
TypeKind::Ref(_, inner) => Some(&inner.kind),
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
let (mut value, ty) = lower_expr(builder, inner, type_hint);
|
||||||
|
|
||||||
|
// check if its a use directly, to avoid a temporary.
|
||||||
|
value = match value {
|
||||||
|
RValue::Use(op) => RValue::Ref(*mutable, op),
|
||||||
|
value => {
|
||||||
|
let inner_local = builder.add_local(Local::temp(ty.clone()));
|
||||||
|
let inner_place = Place {
|
||||||
|
local: inner_local,
|
||||||
|
projection: Default::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
builder.statements.push(Statement {
|
||||||
|
span: None,
|
||||||
|
kind: StatementKind::StorageLive(inner_local),
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.statements.push(Statement {
|
||||||
|
span: None,
|
||||||
|
kind: StatementKind::Assign(inner_place.clone(), value),
|
||||||
|
});
|
||||||
|
RValue::Ref(*mutable, Operand::Move(inner_place))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let ty = TypeKind::Ref(
|
||||||
|
*mutable,
|
||||||
|
Box::new(TypeInfo {
|
||||||
|
span: None,
|
||||||
|
kind: ty,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
(value, ty)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,7 +535,6 @@ fn lower_binary_expr(
|
||||||
) -> (ir::RValue, TypeKind) {
|
) -> (ir::RValue, TypeKind) {
|
||||||
trace!("lowering binary op: {:?}", op);
|
trace!("lowering binary op: {:?}", op);
|
||||||
|
|
||||||
// todo: if lhs or rhs is a simple place, dont make another temporary?
|
|
||||||
let (lhs, lhs_ty) = if type_hint.is_none() {
|
let (lhs, lhs_ty) = if type_hint.is_none() {
|
||||||
let ty = find_expr_type(builder, lhs)
|
let ty = find_expr_type(builder, lhs)
|
||||||
.unwrap_or_else(|| find_expr_type(builder, rhs).expect("cant find type"));
|
.unwrap_or_else(|| find_expr_type(builder, rhs).expect("cant find type"));
|
||||||
|
@ -474,16 +549,14 @@ fn lower_binary_expr(
|
||||||
lower_expr(builder, rhs, type_hint)
|
lower_expr(builder, rhs, type_hint)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let lhs = match lhs {
|
||||||
|
RValue::Use(op) => op,
|
||||||
|
lhs => {
|
||||||
let lhs_local = builder.add_local(Local::temp(lhs_ty.clone()));
|
let lhs_local = builder.add_local(Local::temp(lhs_ty.clone()));
|
||||||
let rhs_local = builder.add_local(Local::temp(rhs_ty.clone()));
|
|
||||||
let lhs_place = Place {
|
let lhs_place = Place {
|
||||||
local: lhs_local,
|
local: lhs_local,
|
||||||
projection: Default::default(),
|
projection: Default::default(),
|
||||||
};
|
};
|
||||||
let rhs_place = Place {
|
|
||||||
local: rhs_local,
|
|
||||||
projection: Default::default(),
|
|
||||||
};
|
|
||||||
|
|
||||||
builder.statements.push(Statement {
|
builder.statements.push(Statement {
|
||||||
span: None,
|
span: None,
|
||||||
|
@ -494,6 +567,18 @@ fn lower_binary_expr(
|
||||||
span: None,
|
span: None,
|
||||||
kind: StatementKind::Assign(lhs_place.clone(), lhs),
|
kind: StatementKind::Assign(lhs_place.clone(), lhs),
|
||||||
});
|
});
|
||||||
|
Operand::Move(lhs_place)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let rhs = match rhs {
|
||||||
|
RValue::Use(op) => op,
|
||||||
|
rhs => {
|
||||||
|
let rhs_local = builder.add_local(Local::temp(rhs_ty.clone()));
|
||||||
|
let rhs_place = Place {
|
||||||
|
local: rhs_local,
|
||||||
|
projection: Default::default(),
|
||||||
|
};
|
||||||
|
|
||||||
builder.statements.push(Statement {
|
builder.statements.push(Statement {
|
||||||
span: None,
|
span: None,
|
||||||
|
@ -504,9 +589,9 @@ fn lower_binary_expr(
|
||||||
span: None,
|
span: None,
|
||||||
kind: StatementKind::Assign(rhs_place.clone(), rhs),
|
kind: StatementKind::Assign(rhs_place.clone(), rhs),
|
||||||
});
|
});
|
||||||
|
Operand::Move(rhs_place)
|
||||||
let lhs = Operand::Move(lhs_place);
|
}
|
||||||
let rhs = Operand::Move(rhs_place);
|
};
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
ast::BinaryOp::Arith(op, _) => (
|
ast::BinaryOp::Arith(op, _) => (
|
||||||
|
@ -791,10 +876,19 @@ fn lower_path(builder: &mut BodyBuilder, info: &ast::PathExpr) -> (ir::Place, Ty
|
||||||
.expect("local not found");
|
.expect("local not found");
|
||||||
let ty = builder.body.locals[local].ty.kind.clone();
|
let ty = builder.body.locals[local].ty.kind.clone();
|
||||||
|
|
||||||
|
let projection = Vec::new();
|
||||||
|
|
||||||
|
for extra in &info.extra {
|
||||||
|
match extra {
|
||||||
|
ast::PathSegment::Field(_) => todo!(),
|
||||||
|
ast::PathSegment::Index { .. } => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
(
|
(
|
||||||
Place {
|
Place {
|
||||||
local,
|
local,
|
||||||
projection: Default::default(), // todo, field array deref
|
projection: projection.into(), // todo, field array deref
|
||||||
},
|
},
|
||||||
ty,
|
ty,
|
||||||
)
|
)
|
||||||
|
|
|
@ -160,7 +160,7 @@ pub(crate) PathExpr: ast::PathExpr = {
|
||||||
first,
|
first,
|
||||||
extra: extra.unwrap_or(vec![]),
|
extra: extra.unwrap_or(vec![]),
|
||||||
span: ast::Span::new(lo, hi),
|
span: ast::Span::new(lo, hi),
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub PathSegments: Vec<ast::PathSegment> = {
|
pub PathSegments: Vec<ast::PathSegment> = {
|
||||||
|
@ -215,9 +215,10 @@ pub(crate) LetStmt: ast::LetStmt = {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) AssignStmt: ast::AssignStmt = {
|
pub(crate) AssignStmt: ast::AssignStmt = {
|
||||||
<lo:@L> <name:PathExpr> "=" <value:Expression> <hi:@R> => ast::AssignStmt {
|
<lo:@L> <deref:"*"*> <name:PathExpr> "=" <value:Expression> <hi:@R> => ast::AssignStmt {
|
||||||
name,
|
name,
|
||||||
value,
|
value,
|
||||||
|
deref_times: deref.len(),
|
||||||
span: ast::Span::new(lo, hi),
|
span: ast::Span::new(lo, hi),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -268,32 +269,38 @@ pub(crate) IfStmt: ast::IfStmt = {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) Term: ast::Expression = {
|
pub(crate) Term: ast::Expression = {
|
||||||
|
#[precedence(level="0")]
|
||||||
<ValueExpr> => ast::Expression::Value(<>),
|
<ValueExpr> => ast::Expression::Value(<>),
|
||||||
<FnCallExpr> => ast::Expression::FnCall(<>),
|
<FnCallExpr> => ast::Expression::FnCall(<>),
|
||||||
|
#[precedence(level="2")] #[assoc(side="left")]
|
||||||
"(" <Expression> ")",
|
"(" <Expression> ")",
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) Expression: ast::Expression = {
|
pub(crate) Expression: ast::Expression = {
|
||||||
#[precedence(level="0")]
|
#[precedence(level="0")]
|
||||||
<Term>,
|
<Term>,
|
||||||
|
#[precedence(level="1")] #[assoc(side="left")]
|
||||||
|
"&" "mut" <Expression> => ast::Expression::AsRef(Box::new(<>), true),
|
||||||
|
"&" <Expression> => ast::Expression::AsRef(Box::new(<>), false),
|
||||||
|
"*" <Expression> => ast::Expression::Deref(Box::new(<>)),
|
||||||
<op:UnaryOp> <rhs:Expression> => ast::Expression::Unary(
|
<op:UnaryOp> <rhs:Expression> => ast::Expression::Unary(
|
||||||
op,
|
op,
|
||||||
Box::new(rhs)
|
Box::new(rhs)
|
||||||
),
|
),
|
||||||
// <op:UnaryOp> <e:Expression> => ast::Expression::UnaryOp(op, Box::new(e)),
|
|
||||||
#[precedence(level="1")] #[assoc(side="left")]
|
#[precedence(level="2")] #[assoc(side="left")]
|
||||||
<lhs:Expression> <op:BinaryFirstLvlOp> <rhs:Expression> => ast::Expression::Binary(
|
<lhs:Expression> <op:BinaryFirstLvlOp> <rhs:Expression> => ast::Expression::Binary(
|
||||||
Box::new(lhs),
|
Box::new(lhs),
|
||||||
op,
|
op,
|
||||||
Box::new(rhs)
|
Box::new(rhs)
|
||||||
),
|
),
|
||||||
#[precedence(level="2")] #[assoc(side="left")]
|
#[precedence(level="3")] #[assoc(side="left")]
|
||||||
<lhs:Expression> <op:BinarySecondLvlOp> <rhs:Expression> => ast::Expression::Binary(
|
<lhs:Expression> <op:BinarySecondLvlOp> <rhs:Expression> => ast::Expression::Binary(
|
||||||
Box::new(lhs),
|
Box::new(lhs),
|
||||||
op,
|
op,
|
||||||
Box::new(rhs)
|
Box::new(rhs)
|
||||||
),
|
),
|
||||||
#[precedence(level="3")] #[assoc(side="left")]
|
#[precedence(level="4")] #[assoc(side="left")]
|
||||||
<lhs:Expression> <op:BinaryThirdLvlOp> <rhs:Expression> => ast::Expression::Binary(
|
<lhs:Expression> <op:BinaryThirdLvlOp> <rhs:Expression> => ast::Expression::Binary(
|
||||||
Box::new(lhs),
|
Box::new(lhs),
|
||||||
op,
|
op,
|
||||||
|
|
Loading…
Reference in a new issue