mirror of
https://github.com/edg-l/edlang.git
synced 2024-11-23 08:28:24 +00:00
array codegen
This commit is contained in:
parent
82fbd609c1
commit
a6d4bee05a
|
@ -31,7 +31,7 @@ enum Commands {
|
|||
#[arg(long)]
|
||||
name: Option<String>,
|
||||
|
||||
/// Use a binary (application) template [default]
|
||||
/// Use a binary (application) template \[default\]
|
||||
#[arg(long, group = "binary", default_value_t = true)]
|
||||
bin: bool,
|
||||
|
||||
|
|
|
@ -48,13 +48,20 @@ pub struct Ident {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
// T: A + B
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct Type {
|
||||
pub name: Ident,
|
||||
pub generics: Vec<Type>,
|
||||
pub qualifiers: Vec<TypeQualifier>,
|
||||
pub span: Span,
|
||||
pub enum Type {
|
||||
Basic {
|
||||
name: Ident,
|
||||
generics: Vec<Type>,
|
||||
qualifiers: Vec<TypeQualifier>,
|
||||
span: Span,
|
||||
},
|
||||
Array {
|
||||
of: Box<Self>,
|
||||
size: Option<u32>,
|
||||
qualifiers: Vec<TypeQualifier>,
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
|
@ -184,6 +191,7 @@ pub enum Expression {
|
|||
Value(ValueExpr),
|
||||
FnCall(FnCallExpr),
|
||||
StructInit(StructInitExpr),
|
||||
ArrayInit(ArrayInitExpr),
|
||||
Unary(UnaryOp, Box<Self>),
|
||||
Binary(Box<Self>, BinaryOp, Box<Self>),
|
||||
Deref(Box<Self>, Span),
|
||||
|
@ -209,11 +217,18 @@ pub struct StructInitField {
|
|||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct StructInitExpr {
|
||||
pub name: Type,
|
||||
pub name: Ident,
|
||||
pub generics: Vec<Type>,
|
||||
pub fields: BTreeMap<Ident, StructInitField>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct ArrayInitExpr {
|
||||
pub data: Vec<Expression>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct FnCallExpr {
|
||||
pub name: Ident,
|
||||
|
|
|
@ -21,7 +21,7 @@ use inkwell::{
|
|||
values::{BasicValue, BasicValueEnum, PointerValue},
|
||||
AddressSpace,
|
||||
};
|
||||
use ir::{LocalKind, ModuleBody, ProgramBody, TypeInfo, ValueTree};
|
||||
use ir::{LocalKind, ModuleBody, Place, ProgramBody, TypeInfo, ValueTree};
|
||||
use llvm_sys::debuginfo::LLVMDIFlagPublic;
|
||||
use tracing::{info, trace};
|
||||
|
||||
|
@ -160,7 +160,11 @@ pub fn compile(session: &Session, program: &ProgramBody) -> Result<PathBuf, Box<
|
|||
compile_module(&mut module_ctx, *module_id);
|
||||
|
||||
module_ctx.di_builder.finalize();
|
||||
module_ctx.module.verify()?;
|
||||
|
||||
if let Err(e) = module_ctx.module.verify() {
|
||||
eprintln!("{}", e.to_str()?);
|
||||
Err(e)?;
|
||||
}
|
||||
|
||||
// todo link modules together
|
||||
llvm_modules.push_back(module_ctx.module);
|
||||
|
@ -458,7 +462,44 @@ fn compile_fn(ctx: &ModuleCompileCtx, fn_id: DefId) -> Result<(), BuilderError>
|
|||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
ir::PlaceElem::Index { .. } => todo!(),
|
||||
ir::PlaceElem::Index { local } => {
|
||||
let value = compile_load_place(
|
||||
ctx,
|
||||
fn_id,
|
||||
&locals,
|
||||
&Place {
|
||||
local: *local,
|
||||
projection: Default::default(),
|
||||
},
|
||||
false,
|
||||
)?;
|
||||
|
||||
ptr = unsafe {
|
||||
ctx.builder.build_in_bounds_gep(
|
||||
ptr.get_type(),
|
||||
ptr,
|
||||
&[
|
||||
ctx.ctx.context.i32_type().const_int(0, false),
|
||||
value.0.into_int_value(),
|
||||
],
|
||||
"constindex",
|
||||
)?
|
||||
};
|
||||
}
|
||||
ir::PlaceElem::ConstIndex { index } => {
|
||||
ptr = unsafe {
|
||||
ctx.builder.build_in_bounds_gep(
|
||||
ptr.get_type(),
|
||||
ptr,
|
||||
&[ctx
|
||||
.ctx
|
||||
.context
|
||||
.i32_type()
|
||||
.const_int((*index) as u64, false)],
|
||||
"constindex",
|
||||
)?
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1034,6 +1075,7 @@ fn compile_rvalue<'ctx>(
|
|||
}
|
||||
ir::PlaceElem::Field { .. } => todo!(),
|
||||
ir::PlaceElem::Index { .. } => todo!(),
|
||||
ir::PlaceElem::ConstIndex { .. } => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1224,6 +1266,7 @@ fn compile_load_place<'ctx>(
|
|||
}
|
||||
}
|
||||
ir::PlaceElem::Index { .. } => todo!(),
|
||||
ir::PlaceElem::ConstIndex { .. } => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1351,7 +1394,7 @@ fn compile_basic_type<'ctx>(
|
|||
match &ty.kind {
|
||||
ir::TypeKind::Unit => todo!(),
|
||||
ir::TypeKind::Bool => ctx.ctx.context.bool_type().as_basic_type_enum(),
|
||||
ir::TypeKind::Char => ctx.ctx.context.i32_type().as_basic_type_enum(),
|
||||
ir::TypeKind::Char => ctx.ctx.context.i8_type().as_basic_type_enum(),
|
||||
ir::TypeKind::Int(ty) => match ty {
|
||||
ir::IntTy::I128 => ctx.ctx.context.i128_type().as_basic_type_enum(),
|
||||
ir::IntTy::I64 => ctx.ctx.context.i64_type().as_basic_type_enum(),
|
||||
|
@ -1437,6 +1480,26 @@ fn compile_basic_type<'ctx>(
|
|||
.struct_type(&fields, false)
|
||||
.as_basic_type_enum()
|
||||
}
|
||||
ir::TypeKind::Slice(inner, size) => {
|
||||
let inner = compile_basic_type(ctx, inner);
|
||||
if let Some(size) = size {
|
||||
inner.array_type(*size).as_basic_type_enum()
|
||||
} else {
|
||||
ctx.ctx
|
||||
.context
|
||||
.struct_type(
|
||||
&[
|
||||
ctx.ctx
|
||||
.context
|
||||
.ptr_type(AddressSpace::default())
|
||||
.as_basic_type_enum(),
|
||||
ctx.ctx.context.i64_type().as_basic_type_enum(),
|
||||
],
|
||||
false,
|
||||
)
|
||||
.as_basic_type_enum()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1631,5 +1694,52 @@ fn compile_debug_type<'ctx>(ctx: &ModuleCompileCtx<'ctx, '_>, ty: &ir::TypeInfo)
|
|||
)
|
||||
.as_type()
|
||||
}
|
||||
ir::TypeKind::Slice(inner, size) => {
|
||||
let real_ty = compile_basic_type(ctx, ty);
|
||||
let inner_type = compile_debug_type(ctx, inner);
|
||||
|
||||
if let Some(size) = size {
|
||||
ctx.di_builder
|
||||
.create_array_type(
|
||||
inner_type,
|
||||
ctx.target_data.get_abi_size(&real_ty),
|
||||
ctx.target_data.get_abi_alignment(&real_ty),
|
||||
#[allow(clippy::single_range_in_vec_init)] // false positive
|
||||
&[0..((*size) as i64)],
|
||||
)
|
||||
.as_type()
|
||||
} else {
|
||||
ctx.di_builder
|
||||
.create_struct_type(
|
||||
ctx.di_namespace,
|
||||
"str",
|
||||
ctx.di_unit.get_file(),
|
||||
0,
|
||||
ctx.target_data.get_bit_size(&real_ty),
|
||||
ctx.target_data.get_abi_alignment(&real_ty),
|
||||
0,
|
||||
None,
|
||||
&[
|
||||
ctx.di_builder
|
||||
.create_pointer_type(
|
||||
name,
|
||||
inner_type,
|
||||
(ctx.target_data.get_pointer_byte_size(None) * 8).into(),
|
||||
ctx.target_data.get_pointer_byte_size(None),
|
||||
AddressSpace::default(),
|
||||
)
|
||||
.as_type(),
|
||||
ctx.di_builder
|
||||
.create_basic_type(name, 64, 0x7, LLVMDIFlagPublic)
|
||||
.unwrap()
|
||||
.as_type(),
|
||||
],
|
||||
0,
|
||||
None,
|
||||
"str",
|
||||
)
|
||||
.as_type()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,7 +60,6 @@ pub fn link_binary(objects: &[PathBuf], output_filename: &Path) -> std::io::Resu
|
|||
let mut args = vec![
|
||||
"-L/usr/local/lib",
|
||||
"-L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib",
|
||||
&input_path.display().to_string(),
|
||||
];
|
||||
|
||||
args.extend(objects.iter().map(|x| x.as_str()));
|
||||
|
|
|
@ -262,6 +262,7 @@ pub enum TypeKind {
|
|||
Ref(bool, Box<TypeInfo>),
|
||||
// name for print purposes
|
||||
Struct(DefId, String), // todo, add generics
|
||||
Slice(Box<TypeInfo>, Option<u32>),
|
||||
}
|
||||
|
||||
impl TypeKind {
|
||||
|
@ -308,6 +309,7 @@ impl TypeKind {
|
|||
TypeKind::Ref(_, inner) => inner.kind.get_falsy_value(),
|
||||
TypeKind::Struct(_, _name) => todo!(),
|
||||
TypeKind::Str => todo!(),
|
||||
TypeKind::Slice(_, _) => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -351,6 +353,15 @@ impl fmt::Display for TypeKind {
|
|||
write!(f, "&{word} {}", inner.kind)
|
||||
}
|
||||
TypeKind::Struct(_, name) => write!(f, "{}", name),
|
||||
TypeKind::Slice(inner, size) => {
|
||||
let size = if let Some(size) = size {
|
||||
format!("; {size}")
|
||||
} else {
|
||||
"".to_string()
|
||||
};
|
||||
|
||||
write!(f, "[{}{size}]", inner.kind)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -477,6 +488,7 @@ pub enum PlaceElem {
|
|||
Deref,
|
||||
Field { field_idx: usize },
|
||||
Index { local: usize },
|
||||
ConstIndex { index: usize },
|
||||
}
|
||||
|
||||
impl TypeKind {
|
||||
|
|
|
@ -645,15 +645,16 @@ fn find_expr_type(builder: &mut BodyBuilder, info: &ast::Expression) -> Option<T
|
|||
.get_module_body()
|
||||
.symbols
|
||||
.structs
|
||||
.get(&info.name.name.name)
|
||||
.get(&info.name.name)
|
||||
.expect("struct not found");
|
||||
ir::TypeKind::Struct(id, info.name.name.name.clone())
|
||||
ir::TypeKind::Struct(id, info.name.name.clone())
|
||||
}
|
||||
ast::Expression::Cast(_, _new_ty, _) => {
|
||||
// checks?
|
||||
|
||||
todo!()
|
||||
}
|
||||
ast::Expression::ArrayInit(_) => todo!(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -762,7 +763,7 @@ fn lower_expr(
|
|||
.get_module_body()
|
||||
.symbols
|
||||
.structs
|
||||
.get(&info.name.name.name)
|
||||
.get(&info.name.name)
|
||||
.expect("struct not found");
|
||||
let struct_body = builder.ctx.body.structs.get(&id).unwrap().clone();
|
||||
let ty = TypeKind::Struct(id, struct_body.name.clone());
|
||||
|
@ -832,6 +833,45 @@ fn lower_expr(
|
|||
|
||||
(rvalue, kind, *span)
|
||||
}
|
||||
ast::Expression::ArrayInit(info) => {
|
||||
let ty = if let Some(type_hint) = type_hint {
|
||||
type_hint.clone()
|
||||
} else {
|
||||
todo!()
|
||||
};
|
||||
|
||||
let inner = if let TypeKind::Slice(inner, _) = &ty.kind {
|
||||
inner
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let local = builder.add_temp_local(ty.kind.clone());
|
||||
builder.statements.push(Statement {
|
||||
span: None,
|
||||
kind: StatementKind::StorageLive(local),
|
||||
});
|
||||
let place = Place {
|
||||
local,
|
||||
projection: Default::default(),
|
||||
};
|
||||
for (i, x) in info.data.iter().enumerate() {
|
||||
let (value, _ty, span) = lower_expr(builder, x, Some(inner))?;
|
||||
let mut place = place.clone();
|
||||
place.projection.push(PlaceElem::ConstIndex { index: i });
|
||||
|
||||
builder.statements.push(Statement {
|
||||
span: Some(span),
|
||||
kind: StatementKind::Assign(place, value),
|
||||
});
|
||||
}
|
||||
|
||||
(
|
||||
RValue::Use(Operand::Move(place), info.span),
|
||||
ty.kind,
|
||||
info.span,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1096,9 +1136,7 @@ fn lower_value(
|
|||
span: None,
|
||||
kind: ir::TypeKind::Char,
|
||||
},
|
||||
kind: ir::ConstKind::Value(ir::ValueTree::Leaf(ir::ConstValue::U32(
|
||||
(*value) as u32,
|
||||
))),
|
||||
kind: ir::ConstKind::Value(ir::ValueTree::Leaf(ir::ConstValue::U8((*value) as u8))),
|
||||
}),
|
||||
TypeKind::Char,
|
||||
*span,
|
||||
|
@ -1475,82 +1513,106 @@ pub fn lower_type(
|
|||
t: &ast::Type,
|
||||
module_id: DefId,
|
||||
) -> Result<ir::TypeInfo, LoweringError> {
|
||||
let mut ty = match t.name.name.as_str() {
|
||||
"()" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Unit,
|
||||
},
|
||||
"u8" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Uint(ir::UintTy::U8),
|
||||
},
|
||||
"u16" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Uint(ir::UintTy::U16),
|
||||
},
|
||||
"u32" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Uint(ir::UintTy::U32),
|
||||
},
|
||||
"u64" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Uint(ir::UintTy::U64),
|
||||
},
|
||||
"u128" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Uint(ir::UintTy::U128),
|
||||
},
|
||||
"i8" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Int(ir::IntTy::I8),
|
||||
},
|
||||
"i16" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Int(ir::IntTy::I16),
|
||||
},
|
||||
"i32" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Int(ir::IntTy::I32),
|
||||
},
|
||||
"i64" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Int(ir::IntTy::I64),
|
||||
},
|
||||
"i128" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Int(ir::IntTy::I128),
|
||||
},
|
||||
"char" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Char,
|
||||
},
|
||||
"bool" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Bool,
|
||||
},
|
||||
"str" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Str,
|
||||
},
|
||||
other => {
|
||||
let module = ctx.body.modules.get(&module_id).expect("module not found");
|
||||
if let Some(struct_id) = module.symbols.structs.get(other) {
|
||||
let struct_body = ctx.body.structs.get(struct_id).unwrap();
|
||||
ir::TypeInfo {
|
||||
span: Some(struct_body.span),
|
||||
kind: TypeKind::Struct(*struct_id, struct_body.name.clone()),
|
||||
let (mut ty, qualifiers) = match t {
|
||||
ast::Type::Basic {
|
||||
name,
|
||||
generics: _,
|
||||
qualifiers,
|
||||
span,
|
||||
} => {
|
||||
let ty = match name.name.as_str() {
|
||||
"()" => ir::TypeInfo {
|
||||
span: Some(*span),
|
||||
kind: ir::TypeKind::Unit,
|
||||
},
|
||||
"u8" => ir::TypeInfo {
|
||||
span: Some(*span),
|
||||
kind: ir::TypeKind::Uint(ir::UintTy::U8),
|
||||
},
|
||||
"u16" => ir::TypeInfo {
|
||||
span: Some(*span),
|
||||
kind: ir::TypeKind::Uint(ir::UintTy::U16),
|
||||
},
|
||||
"u32" => ir::TypeInfo {
|
||||
span: Some(*span),
|
||||
kind: ir::TypeKind::Uint(ir::UintTy::U32),
|
||||
},
|
||||
"u64" => ir::TypeInfo {
|
||||
span: Some(*span),
|
||||
kind: ir::TypeKind::Uint(ir::UintTy::U64),
|
||||
},
|
||||
"u128" => ir::TypeInfo {
|
||||
span: Some(*span),
|
||||
kind: ir::TypeKind::Uint(ir::UintTy::U128),
|
||||
},
|
||||
"i8" => ir::TypeInfo {
|
||||
span: Some(*span),
|
||||
kind: ir::TypeKind::Int(ir::IntTy::I8),
|
||||
},
|
||||
"i16" => ir::TypeInfo {
|
||||
span: Some(*span),
|
||||
kind: ir::TypeKind::Int(ir::IntTy::I16),
|
||||
},
|
||||
"i32" => ir::TypeInfo {
|
||||
span: Some(*span),
|
||||
kind: ir::TypeKind::Int(ir::IntTy::I32),
|
||||
},
|
||||
"i64" => ir::TypeInfo {
|
||||
span: Some(*span),
|
||||
kind: ir::TypeKind::Int(ir::IntTy::I64),
|
||||
},
|
||||
"i128" => ir::TypeInfo {
|
||||
span: Some(*span),
|
||||
kind: ir::TypeKind::Int(ir::IntTy::I128),
|
||||
},
|
||||
"char" => ir::TypeInfo {
|
||||
span: Some(*span),
|
||||
kind: ir::TypeKind::Char,
|
||||
},
|
||||
"bool" => ir::TypeInfo {
|
||||
span: Some(*span),
|
||||
kind: ir::TypeKind::Bool,
|
||||
},
|
||||
"str" => ir::TypeInfo {
|
||||
span: Some(*span),
|
||||
kind: ir::TypeKind::Str,
|
||||
},
|
||||
other => {
|
||||
let module = ctx.body.modules.get(&module_id).expect("module not found");
|
||||
if let Some(struct_id) = module.symbols.structs.get(other) {
|
||||
let struct_body = ctx.body.structs.get(struct_id).unwrap();
|
||||
ir::TypeInfo {
|
||||
span: Some(struct_body.span),
|
||||
kind: TypeKind::Struct(*struct_id, struct_body.name.clone()),
|
||||
}
|
||||
} else {
|
||||
Err(LoweringError::UnrecognizedType {
|
||||
span: name.span,
|
||||
name: name.name.clone(),
|
||||
file_id: module.file_id,
|
||||
})?
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Err(LoweringError::UnrecognizedType {
|
||||
span: t.name.span,
|
||||
name: t.name.name.clone(),
|
||||
file_id: module.file_id,
|
||||
})?
|
||||
}
|
||||
};
|
||||
(ty, qualifiers)
|
||||
}
|
||||
ast::Type::Array {
|
||||
of,
|
||||
size,
|
||||
qualifiers,
|
||||
span,
|
||||
} => {
|
||||
let ty = ir::TypeInfo {
|
||||
span: Some(*span),
|
||||
kind: ir::TypeKind::Slice(Box::new(lower_type(ctx, of, module_id)?), *size),
|
||||
};
|
||||
(ty, qualifiers)
|
||||
}
|
||||
};
|
||||
|
||||
for qualifier in t.qualifiers.iter().rev() {
|
||||
let span = ty.span;
|
||||
|
||||
for qualifier in qualifiers.iter().rev() {
|
||||
let kind = match qualifier {
|
||||
ast::TypeQualifier::Ref => TypeKind::Ref(false, Box::new(ty)),
|
||||
ast::TypeQualifier::RefMut => TypeKind::Ref(true, Box::new(ty)),
|
||||
|
@ -1558,10 +1620,7 @@ pub fn lower_type(
|
|||
ast::TypeQualifier::PtrMut => TypeKind::Ptr(true, Box::new(ty)),
|
||||
};
|
||||
|
||||
ty = TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind,
|
||||
};
|
||||
ty = TypeInfo { span, kind };
|
||||
}
|
||||
|
||||
Ok(ty)
|
||||
|
|
|
@ -151,34 +151,36 @@ pub(crate) TypeQualifier: ast::TypeQualifier = {
|
|||
}
|
||||
|
||||
pub(crate) Type: ast::Type = {
|
||||
<lo:@L> <qualifiers:TypeQualifier*> <name:Ident> <hi:@R> => ast::Type {
|
||||
<lo:@L> <qualifiers:TypeQualifier*> <name:Ident> <hi:@R> => ast::Type::Basic {
|
||||
name,
|
||||
generics: vec![],
|
||||
qualifiers,
|
||||
span: ast::Span::new(lo, hi),
|
||||
},
|
||||
<lo:@L> <qualifiers:TypeQualifier*> <name:Ident> "<" <generics:Comma<Type>> ">" <hi:@R> => ast::Type {
|
||||
<lo:@L> <qualifiers:TypeQualifier*> <name:Ident> "<" <generics:Comma<Type>> ">" <hi:@R> => ast::Type::Basic {
|
||||
name,
|
||||
generics,
|
||||
qualifiers,
|
||||
span: ast::Span::new(lo, hi),
|
||||
},
|
||||
<lo:@L> <qualifiers:TypeQualifier*> "[" <of:Type> "]" <hi:@R> => ast::Type::Array {
|
||||
of: Box::new(of),
|
||||
size: None,
|
||||
qualifiers,
|
||||
span: ast::Span::new(lo, hi),
|
||||
},
|
||||
<lo:@L> <qualifiers:TypeQualifier*> "[" <of:Type> ";" <size:"integer"> "]" <hi:@R> => ast::Type::Array {
|
||||
of: Box::new(of),
|
||||
size: Some(size.try_into().unwrap()),
|
||||
qualifiers,
|
||||
span: ast::Span::new(lo, hi),
|
||||
},
|
||||
}
|
||||
|
||||
/// For things like A::<T> { a: value }
|
||||
pub(crate) IdentWithOptionalType: ast::Type = {
|
||||
<lo:@L> <name:Ident> <hi:@R> => ast::Type {
|
||||
name,
|
||||
generics: vec![],
|
||||
qualifiers: vec![],
|
||||
span: ast::Span::new(lo, hi),
|
||||
},
|
||||
<lo:@L> <name:Ident> "::" "<" <generics:Comma<Type>> ">" <hi:@R> => ast::Type {
|
||||
name,
|
||||
generics,
|
||||
qualifiers: vec![],
|
||||
span: ast::Span::new(lo, hi),
|
||||
},
|
||||
pub(crate) IdentWithGenerics: (ast::Ident, Vec<ast::Type>) = {
|
||||
<name:Ident> => (name, vec![]),
|
||||
<lo:@L> <name:Ident> "::" "<" <generics:Comma<Type>> ">" <hi:@R> => (name, generics),
|
||||
}
|
||||
|
||||
pub(crate) PathExpr: ast::PathExpr = {
|
||||
|
@ -351,6 +353,7 @@ pub(crate) Expression: ast::Expression = {
|
|||
#[precedence(level="5")] #[assoc(side="left")]
|
||||
<lo:@L> <a:Expression> "as" <b: Type> <hi:@R> => ast::Expression::Cast(Box::new(a), b, ast::Span::new(lo, hi)),
|
||||
"(" <StructInitExpr> ")" => ast::Expression::StructInit(<>),
|
||||
<ArrayInitExpr> => ast::Expression::ArrayInit(<>),
|
||||
}
|
||||
|
||||
pub BinaryFirstLvlOp: ast::BinaryOp = {
|
||||
|
@ -412,13 +415,21 @@ pub(crate) StructInitField: (ast::Ident, ast::StructInitField) = {
|
|||
}
|
||||
|
||||
pub(crate) StructInitExpr: ast::StructInitExpr = {
|
||||
<lo:@L> <name:IdentWithOptionalType> "{" <fields:Comma<StructInitField>> "}" <hi:@R> => ast::StructInitExpr {
|
||||
name,
|
||||
<lo:@L> <name:IdentWithGenerics> "{" <fields:Comma<StructInitField>> "}" <hi:@R> => ast::StructInitExpr {
|
||||
name: name.0,
|
||||
generics: name.1,
|
||||
fields: fields.into_iter().collect(),
|
||||
span: ast::Span::new(lo, hi),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) ArrayInitExpr: ast::ArrayInitExpr = {
|
||||
<lo:@L> "[" <data:Comma<Expression>> "]" <hi:@R> => ast::ArrayInitExpr {
|
||||
data: data.into_iter().collect(),
|
||||
span: ast::Span::new(lo, hi),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) FnParam: ast::FnParam = {
|
||||
<lo:@L> <name:Ident> ":" <arg_type:Type> <hi:@R> => ast::FnParam {
|
||||
name,
|
||||
|
|
Loading…
Reference in a new issue