fixed arrays
This commit is contained in:
parent
ad868c0c25
commit
f8abae63b3
12 changed files with 183 additions and 26 deletions
|
|
@ -11,6 +11,7 @@ pub enum TypeAnnot {
|
|||
Function(Vec<TypeAnnot>, Box<TypeAnnot>),
|
||||
Tuple(Vec<TypeAnnot>),
|
||||
Array(Box<TypeAnnot>),
|
||||
FixedArray(Box<TypeAnnot>, i64),
|
||||
Ptr(Box<TypeAnnot>),
|
||||
}
|
||||
|
||||
|
|
@ -208,6 +209,7 @@ pub enum ExprKind {
|
|||
Bool(bool),
|
||||
String(String),
|
||||
Array(Vec<Expr>),
|
||||
FixedArray(Box<Expr>, i64),
|
||||
Tuple(Vec<Expr>),
|
||||
|
||||
StructLit(String, Vec<(String, Expr)>), // Name { a: expr, b: expr }
|
||||
|
|
@ -402,6 +404,7 @@ pub enum TypedExprKind {
|
|||
Bool(bool),
|
||||
String(String),
|
||||
Array(Vec<TypedExpr>),
|
||||
FixedArray(Box<TypedExpr>, usize),
|
||||
Tuple(Vec<TypedExpr>),
|
||||
StructLit(String, Vec<(String, TypedExpr)>),
|
||||
EnumLit(String, String, Vec<TypedExpr>),
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ pub enum CType {
|
|||
Struct(String),
|
||||
UnnamedStruct(Vec<CVarDecl>),
|
||||
Array(Box<CType>), // heap-allocated array wrapper with data pointer, len, capacity
|
||||
FixedArray(Box<CType>, usize), // fixed-size array like int[10]
|
||||
Func(Vec<CType>, Box<CType>), // args and return
|
||||
}
|
||||
|
||||
|
|
@ -48,6 +49,7 @@ impl CType {
|
|||
"struct sui_array_{}",
|
||||
inner.to_string().replace(" ", "_").replace("*", "ptr")
|
||||
),
|
||||
CType::FixedArray(inner, size) => format!("{}*", inner.to_string()), // For now, treat as pointer in type strings
|
||||
CType::Func(args, ret) => {
|
||||
let arg_strs: Vec<String> = args.iter().map(|t| t.to_string()).collect();
|
||||
format!("{} (*)({})", ret.to_string(), arg_strs.join(", "))
|
||||
|
|
|
|||
|
|
@ -148,6 +148,10 @@ impl DeclarationTranspiler {
|
|||
// Arrays are pointers to the element type
|
||||
Ok(CType::Ptr(Box::new(inner_type)))
|
||||
}
|
||||
Some(TypeAnnot::FixedArray(inner, size)) => {
|
||||
let inner_type = self.type_annot_to_c_type(&Some(*inner.clone()))?;
|
||||
Ok(CType::FixedArray(Box::new(inner_type), *size as usize))
|
||||
}
|
||||
Some(TypeAnnot::Tuple(fields)) => {
|
||||
let mut c_fields = Vec::new();
|
||||
for (i, field_annot) in fields.iter().enumerate() {
|
||||
|
|
|
|||
|
|
@ -117,6 +117,11 @@ impl StatementsTranspiler {
|
|||
.collect::<Result<Vec<_>, _>>()?;
|
||||
Ok(CExpr::ArrayLit(c_exprs))
|
||||
}
|
||||
TypedExprKind::FixedArray(expr, size) => {
|
||||
let c_expr = self.transpile_expr(expr)?;
|
||||
let c_exprs = vec![c_expr; *size];
|
||||
Ok(CExpr::ArrayLit(c_exprs))
|
||||
}
|
||||
TypedExprKind::Cast(expr, type_annot) => {
|
||||
let c_expr = self.transpile_expr(expr)?;
|
||||
// Simplified: assuming we can map type annotations to C types
|
||||
|
|
@ -482,6 +487,10 @@ impl StatementsTranspiler {
|
|||
// Arrays are pointers to the element type
|
||||
Ok(CType::Ptr(Box::new(inner_type)))
|
||||
}
|
||||
Type::FixedArray(inner, size) => {
|
||||
let inner_type = self.type_to_ctype(inner)?;
|
||||
Ok(CType::FixedArray(Box::new(inner_type), *size))
|
||||
}
|
||||
Type::Struct(name, _) => Ok(CType::Ptr(Box::new(CType::Struct(name.clone())))),
|
||||
Type::Enum(name, _) => Ok(CType::Ptr(Box::new(CType::Struct(name.clone())))),
|
||||
Type::Tuple(types) => {
|
||||
|
|
@ -536,6 +545,10 @@ impl StatementsTranspiler {
|
|||
// Arrays are pointers to the element type
|
||||
Ok(CType::Ptr(Box::new(inner_type)))
|
||||
}
|
||||
TypeAnnot::FixedArray(inner, size) => {
|
||||
let inner_type = self.type_annot_to_ctype(inner)?;
|
||||
Ok(CType::FixedArray(Box::new(inner_type), *size as usize))
|
||||
}
|
||||
TypeAnnot::Tuple(fields) => {
|
||||
let mut c_fields = Vec::new();
|
||||
for (i, field_annot) in fields.iter().enumerate() {
|
||||
|
|
|
|||
|
|
@ -404,9 +404,23 @@ impl Transpiler {
|
|||
}
|
||||
|
||||
fn generate_var_decl(&self, var: &CVarDecl) -> String {
|
||||
let mut output = format!("{} {}", var.ty.to_string(), var.name);
|
||||
let mut output = match &var.ty {
|
||||
CType::FixedArray(elem_ty, size) => format!("{} {}[{}]", elem_ty.to_string(), var.name, size),
|
||||
_ => format!("{} {}", var.ty.to_string(), var.name),
|
||||
};
|
||||
if let Some(init) = &var.initializer {
|
||||
output.push_str(&format!(" = {}", self.generate_expr(init)));
|
||||
match (&var.ty, init) {
|
||||
(CType::FixedArray(_, _), CExpr::ArrayLit(elements)) => {
|
||||
let vec: Vec<String> = elements
|
||||
.iter()
|
||||
.map(|expr| self.generate_expr(expr))
|
||||
.collect();
|
||||
output.push_str(&format!(" = {{{}}}", vec.join(", ")));
|
||||
}
|
||||
_ => {
|
||||
output.push_str(&format!(" = {}", self.generate_expr(init)));
|
||||
}
|
||||
}
|
||||
}
|
||||
output
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,6 +126,9 @@ impl LambdaLowerer {
|
|||
self.collect_free_vars_expr(expr, lambda_params, free_vars, local_scope);
|
||||
}
|
||||
}
|
||||
ExprKind::FixedArray(expr, _) => {
|
||||
self.collect_free_vars_expr(expr, lambda_params, free_vars, local_scope);
|
||||
}
|
||||
ExprKind::Tuple(exprs) => {
|
||||
for expr in exprs {
|
||||
self.collect_free_vars_expr(expr, lambda_params, free_vars, local_scope);
|
||||
|
|
@ -340,6 +343,10 @@ impl LambdaLowerer {
|
|||
.collect::<Result<Vec<_>, _>>()?;
|
||||
ExprKind::Array(lowered_exprs)
|
||||
}
|
||||
ExprKind::FixedArray(expr, size) => {
|
||||
let lowered_expr = self.lower_expr(expr)?;
|
||||
ExprKind::FixedArray(Box::new(lowered_expr), *size)
|
||||
}
|
||||
ExprKind::Tuple(exprs) => {
|
||||
let lowered_exprs = exprs
|
||||
.iter()
|
||||
|
|
|
|||
|
|
@ -342,6 +342,11 @@ impl Monomorphizer {
|
|||
}
|
||||
TypedExprKind::Array(new_elems)
|
||||
}
|
||||
TypedExprKind::FixedArray(expr, size) => {
|
||||
let (new_expr, expr_needs) = self.monomorphize_expr(expr)?;
|
||||
needs.extend(expr_needs);
|
||||
TypedExprKind::FixedArray(Box::new(new_expr), *size)
|
||||
}
|
||||
|
||||
TypedExprKind::Tuple(elems) => {
|
||||
let mut new_elems = Vec::new();
|
||||
|
|
@ -767,6 +772,10 @@ impl Monomorphizer {
|
|||
let new_inner = self.substitute_in_type_annot(inner, subst_map)?;
|
||||
Ok(TypeAnnot::Array(Box::new(new_inner)))
|
||||
}
|
||||
TypeAnnot::FixedArray(inner, size) => {
|
||||
let new_inner = self.substitute_in_type_annot(inner, subst_map)?;
|
||||
Ok(TypeAnnot::FixedArray(Box::new(new_inner), *size))
|
||||
}
|
||||
TypeAnnot::Ptr(inner) => {
|
||||
let new_inner = self.substitute_in_type_annot(inner, subst_map)?;
|
||||
Ok(TypeAnnot::Ptr(Box::new(new_inner)))
|
||||
|
|
@ -782,6 +791,7 @@ impl Monomorphizer {
|
|||
Type::String => TypeAnnot::Var("string".to_string()),
|
||||
Type::Unit => TypeAnnot::Tuple(Vec::new()),
|
||||
Type::Array(inner) => TypeAnnot::Array(Box::new(self.type_to_type_annot(inner))),
|
||||
Type::FixedArray(inner, size) => TypeAnnot::FixedArray(Box::new(self.type_to_type_annot(inner)), *size as i64),
|
||||
Type::Ptr(inner) => TypeAnnot::Ptr(Box::new(self.type_to_type_annot(inner))),
|
||||
Type::Tuple(types) => {
|
||||
let annots = types.iter().map(|t| self.type_to_type_annot(t)).collect();
|
||||
|
|
@ -901,6 +911,9 @@ impl Monomorphizer {
|
|||
TypeAnnot::Array(inner) => {
|
||||
self.collect_needs_from_type(inner, needs);
|
||||
}
|
||||
TypeAnnot::FixedArray(inner, _) => {
|
||||
self.collect_needs_from_type(inner, needs);
|
||||
}
|
||||
TypeAnnot::Ptr(inner) => {
|
||||
self.collect_needs_from_type(inner, needs);
|
||||
}
|
||||
|
|
@ -932,10 +945,8 @@ impl Monomorphizer {
|
|||
let tys = types.iter().map(|t| self.type_annot_to_type(t)).collect();
|
||||
Type::Tuple(tys)
|
||||
}
|
||||
TypeAnnot::Array(inner) => {
|
||||
let inner_type = self.type_annot_to_type(inner);
|
||||
Type::Array(Box::new(inner_type))
|
||||
}
|
||||
TypeAnnot::Array(inner) => Type::Array(Box::new(self.type_annot_to_type(inner))),
|
||||
TypeAnnot::FixedArray(inner, size) => Type::FixedArray(Box::new(self.type_annot_to_type(inner)), *size as usize),
|
||||
TypeAnnot::Ptr(inner) => {
|
||||
let inner_type = self.type_annot_to_type(inner);
|
||||
Type::Ptr(Box::new(inner_type))
|
||||
|
|
@ -1216,6 +1227,7 @@ fn has_typevars_in_type_annot(ty: &TypeAnnot) -> bool {
|
|||
}
|
||||
TypeAnnot::Tuple(types) => types.iter().any(has_typevars_in_type_annot),
|
||||
TypeAnnot::Array(inner) => has_typevars_in_type_annot(inner),
|
||||
TypeAnnot::FixedArray(inner, _) => has_typevars_in_type_annot(inner),
|
||||
TypeAnnot::Ptr(inner) => has_typevars_in_type_annot(inner),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -912,8 +912,23 @@ impl Parser {
|
|||
}
|
||||
Some((Token::LBracket, _)) => {
|
||||
let inner = self.parse_type_annot()?;
|
||||
self.expect(Token::RBracket)?;
|
||||
TypeAnnot::Array(Box::new(inner))
|
||||
if matches!(self.peek(), Some(Token::Semicolon)) {
|
||||
self.next();
|
||||
let size = match self.next() {
|
||||
Some((Token::Int(n), _)) => n,
|
||||
Some((_, span)) => {
|
||||
return self.error("Expected integer size for fixed array".to_string(), span);
|
||||
}
|
||||
None => {
|
||||
return self.error("Expected integer size for fixed array".to_string(), start..start);
|
||||
}
|
||||
};
|
||||
self.expect(Token::RBracket)?;
|
||||
TypeAnnot::FixedArray(Box::new(inner), size)
|
||||
} else {
|
||||
self.expect(Token::RBracket)?;
|
||||
TypeAnnot::Array(Box::new(inner))
|
||||
}
|
||||
}
|
||||
Some((Token::Bang, _)) => TypeAnnot::Cons("never".to_string(), vec![]),
|
||||
Some((_, span)) => {
|
||||
|
|
@ -1607,25 +1622,44 @@ impl Parser {
|
|||
}
|
||||
Some(Token::LBracket) => {
|
||||
self.next();
|
||||
let mut elements = Vec::new();
|
||||
loop {
|
||||
if matches!(self.peek(), Some(Token::RBracket)) {
|
||||
self.next();
|
||||
break;
|
||||
}
|
||||
elements.push(self.parse_expr()?);
|
||||
|
||||
if matches!(self.peek(), Some(Token::Comma)) {
|
||||
self.next();
|
||||
let first_expr = self.parse_expr()?;
|
||||
if matches!(self.peek(), Some(Token::Semicolon)) {
|
||||
self.next();
|
||||
let size = match self.next() {
|
||||
Some((Token::Int(n), _)) => n,
|
||||
Some((_, span)) => {
|
||||
return self.error("Expected integer size for fixed array".to_string(), span);
|
||||
}
|
||||
None => {
|
||||
return self.error("Expected integer size for fixed array".to_string(), start..start);
|
||||
}
|
||||
};
|
||||
self.expect(Token::RBracket)?;
|
||||
let end = self.peek_span().unwrap_or(start..start).end;
|
||||
Ok(Expr {
|
||||
kind: ExprKind::FixedArray(Box::new(first_expr), size),
|
||||
span: Span::new(&(start..end), self.file.clone()),
|
||||
attributes: Vec::new(),
|
||||
})
|
||||
} else {
|
||||
let mut elements = vec![first_expr];
|
||||
loop {
|
||||
if matches!(self.peek(), Some(Token::RBracket)) {
|
||||
self.next();
|
||||
break;
|
||||
}
|
||||
if matches!(self.peek(), Some(Token::Comma)) {
|
||||
self.next();
|
||||
}
|
||||
elements.push(self.parse_expr()?);
|
||||
}
|
||||
let end = self.peek_span().unwrap_or(start..start).end;
|
||||
Ok(Expr {
|
||||
kind: ExprKind::Array(elements),
|
||||
span: Span::new(&(start..end), self.file.clone()),
|
||||
attributes: Vec::new(),
|
||||
})
|
||||
}
|
||||
|
||||
let end = self.peek_span().unwrap_or(start..start).end;
|
||||
Ok(Expr {
|
||||
kind: ExprKind::Array(elements),
|
||||
span: Span::new(&(start..end), self.file.clone()),
|
||||
attributes: Vec::new(),
|
||||
})
|
||||
}
|
||||
Some(Token::KeywordLet) => {
|
||||
self.next();
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ pub enum Type {
|
|||
Unit,
|
||||
Never,
|
||||
Array(Box<Type>),
|
||||
FixedArray(Box<Type>, usize),
|
||||
Ptr(Box<Type>),
|
||||
Tuple(Vec<Type>),
|
||||
Function(Vec<Type>, Box<Type>),
|
||||
|
|
@ -32,6 +33,7 @@ impl Type {
|
|||
Type::Unit => "()".to_string(),
|
||||
Type::Never => "!".to_string(),
|
||||
Type::Array(inner) => format!("[{}]", inner.to_string()),
|
||||
Type::FixedArray(inner, size) => format!("[{}; {}]", inner.to_string(), size),
|
||||
Type::Ptr(inner) => format!("*{}", inner.to_string()),
|
||||
Type::Tuple(types) => {
|
||||
let type_strs: Vec<String> = types.iter().map(|t| t.to_string()).collect();
|
||||
|
|
@ -1814,6 +1816,14 @@ impl TypeChecker {
|
|||
)
|
||||
}
|
||||
|
||||
ExprKind::FixedArray(expr, size) => {
|
||||
let typed_expr = self.typecheck_expr(expr)?;
|
||||
(
|
||||
TypedExprKind::FixedArray(Box::new(typed_expr.clone()), *size as usize),
|
||||
Type::FixedArray(Box::new(typed_expr.ty), *size as usize),
|
||||
)
|
||||
}
|
||||
|
||||
ExprKind::Tuple(elements) => {
|
||||
let mut typed_elements = Vec::new();
|
||||
let mut types = Vec::new();
|
||||
|
|
@ -2171,7 +2181,7 @@ impl TypeChecker {
|
|||
}
|
||||
|
||||
let element_type = match &typed_array.ty {
|
||||
Type::Array(elem_ty) => (**elem_ty).clone(),
|
||||
Type::Array(elem_ty) | Type::FixedArray(elem_ty, _) => (**elem_ty).clone(),
|
||||
ty => {
|
||||
return Err(TypeError {
|
||||
kind: TypeErrorKind::NotAnArray(ty.clone()),
|
||||
|
|
@ -2850,6 +2860,9 @@ impl TypeChecker {
|
|||
TypeAnnot::Array(inner) => {
|
||||
Type::Array(Box::new(self.substitute_type(inner, subst_map)))
|
||||
}
|
||||
TypeAnnot::FixedArray(inner, size) => {
|
||||
Type::FixedArray(Box::new(self.substitute_type(inner, subst_map)), *size as usize)
|
||||
}
|
||||
TypeAnnot::Ptr(inner) => Type::Ptr(Box::new(self.substitute_type(inner, subst_map))),
|
||||
TypeAnnot::Tuple(types) => {
|
||||
let substituted_types: Vec<Type> = types
|
||||
|
|
@ -2923,6 +2936,7 @@ impl TypeChecker {
|
|||
Type::Tuple(tuple_types)
|
||||
}
|
||||
TypeAnnot::Array(inner) => Type::Array(Box::new(self.type_annot_to_type(inner))),
|
||||
TypeAnnot::FixedArray(inner, size) => Type::FixedArray(Box::new(self.type_annot_to_type(inner)), *size as usize),
|
||||
TypeAnnot::Ptr(inner) => Type::Ptr(Box::new(self.type_annot_to_type(inner))),
|
||||
}
|
||||
}
|
||||
|
|
@ -2937,6 +2951,7 @@ impl TypeChecker {
|
|||
(Type::Unit, Type::Unit) => true,
|
||||
(Type::Never, _) | (_, Type::Never) => true,
|
||||
(Type::Array(a), Type::Array(b)) => self.types_compatible(a, b),
|
||||
(Type::FixedArray(a, s1), Type::FixedArray(b, s2)) => s1 == s2 && self.types_compatible(a, b),
|
||||
(Type::Ptr(a), Type::Ptr(b)) => self.types_compatible(a, b),
|
||||
(Type::Tuple(a), Type::Tuple(b)) => {
|
||||
a.len() == b.len()
|
||||
|
|
|
|||
47
tests/fixed_arrays.c
Normal file
47
tests/fixed_arrays.c
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#include "libsuicmez/libsuicmez.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
void* gc_alloc(const TypeInfo* type, size_t size);
|
||||
void gc_init(void);
|
||||
void gc_shutdown(void);
|
||||
|
||||
// Helper for allocating arrays
|
||||
static void* suic_alloc_array(const TypeInfo* type, size_t elem_size, size_t len, void* init_data) {
|
||||
void* ptr = gc_alloc(type, elem_size * len);
|
||||
if (init_data) memcpy(ptr, init_data, elem_size * len);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// Helper for allocating structs
|
||||
static void* suic_alloc_struct(const TypeInfo* type, size_t size, void* init_data) {
|
||||
void* ptr = gc_alloc(type, size);
|
||||
if (init_data) memcpy(ptr, init_data, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int suic_main(void);
|
||||
|
||||
|
||||
int suic_main(void) {
|
||||
int arr[5] = {42, 42, 42, 42, 42};
|
||||
int x = arr[2];
|
||||
return x;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// Initialize GC
|
||||
gc_init();
|
||||
// init globals
|
||||
// init event loop
|
||||
int result = suic_main();
|
||||
// Shutdown GC
|
||||
gc_shutdown();
|
||||
return result;
|
||||
}
|
||||
|
||||
BIN
tests/fixed_arrays.o
Executable file
BIN
tests/fixed_arrays.o
Executable file
Binary file not shown.
6
tests/fixed_arrays.sui
Normal file
6
tests/fixed_arrays.sui
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# Fixed array test
|
||||
fn main() -> int do
|
||||
let arr: [int; 5] = [42; 5];
|
||||
let x = arr[2];
|
||||
x
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue