const kw
This commit is contained in:
parent
dca10507c0
commit
22afdb20a4
13 changed files with 2055 additions and 1188 deletions
1482
game/client.c
1482
game/client.c
File diff suppressed because it is too large
Load diff
1174
game/client.c.bak
Normal file
1174
game/client.c.bak
Normal file
File diff suppressed because it is too large
Load diff
18
src/ast.rs
18
src/ast.rs
|
|
@ -67,6 +67,7 @@ pub enum ASTNodeKind {
|
|||
Function(Function),
|
||||
Extern(Extern),
|
||||
Load(Load),
|
||||
Const(Const),
|
||||
Struct(Struct),
|
||||
Enum(Enum),
|
||||
Impl(Impl),
|
||||
|
|
@ -80,6 +81,13 @@ pub struct Use {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Const {
|
||||
pub name: String,
|
||||
pub typ: Option<TypeAnnot>,
|
||||
pub value: Expr,
|
||||
}
|
||||
|
||||
// ? implies OPTIONAL here
|
||||
// \( implies the presence of (. same for /)
|
||||
|
||||
|
|
@ -265,6 +273,8 @@ pub enum BinOp {
|
|||
Or,
|
||||
BitwiseAnd,
|
||||
BitwiseOr,
|
||||
LShift,
|
||||
RShift,
|
||||
Eq,
|
||||
Neq,
|
||||
Lt,
|
||||
|
|
@ -314,6 +324,7 @@ pub enum TypedASTNodeKind {
|
|||
Function(TypedFunction),
|
||||
Extern(TypedExtern),
|
||||
Load(TypedLoad),
|
||||
Const(TypedConst),
|
||||
Struct(TypedStruct),
|
||||
Enum(TypedEnum),
|
||||
Impl(TypedImpl),
|
||||
|
|
@ -347,6 +358,13 @@ pub struct TypedLoad {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TypedConst {
|
||||
pub name: String,
|
||||
pub typ: Option<TypeAnnot>,
|
||||
pub value: TypedExpr,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TypedStruct {
|
||||
pub name: String,
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ pub struct CVarDecl {
|
|||
pub name: String,
|
||||
pub ty: CType,
|
||||
pub initializer: Option<CExpr>,
|
||||
pub is_const: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
|
|
@ -120,6 +121,8 @@ pub enum CBinaryOp {
|
|||
Or,
|
||||
BitwiseAnd,
|
||||
BitwiseOr,
|
||||
LShift,
|
||||
RShift,
|
||||
}
|
||||
|
||||
impl CBinaryOp {
|
||||
|
|
@ -140,6 +143,8 @@ impl CBinaryOp {
|
|||
CBinaryOp::Or => "||",
|
||||
CBinaryOp::BitwiseAnd => "&",
|
||||
CBinaryOp::BitwiseOr => "|",
|
||||
CBinaryOp::LShift => "<<",
|
||||
CBinaryOp::RShift => ">>",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ impl DeclarationTranspiler {
|
|||
name: field.name.clone(),
|
||||
ty: field_type,
|
||||
initializer: None,
|
||||
is_const: false,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -53,6 +54,7 @@ impl DeclarationTranspiler {
|
|||
name: name.clone(),
|
||||
ty: param_type,
|
||||
initializer: None,
|
||||
is_const: false,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -81,6 +83,7 @@ impl DeclarationTranspiler {
|
|||
name: field_name,
|
||||
ty: c_type,
|
||||
initializer: None,
|
||||
is_const: false,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -100,6 +103,7 @@ impl DeclarationTranspiler {
|
|||
name: field_name,
|
||||
ty: CType::Struct(struct_name),
|
||||
initializer: None,
|
||||
is_const: false,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -115,11 +119,13 @@ impl DeclarationTranspiler {
|
|||
name: "discriminant".to_string(),
|
||||
ty: CType::Int,
|
||||
initializer: None,
|
||||
is_const: false,
|
||||
},
|
||||
CVarDecl {
|
||||
name: "data".to_string(),
|
||||
ty: CType::Struct(union_name_clone),
|
||||
initializer: None,
|
||||
is_const: false,
|
||||
},
|
||||
];
|
||||
|
||||
|
|
@ -160,6 +166,7 @@ impl DeclarationTranspiler {
|
|||
name: format!("field{}", i),
|
||||
ty: field_type,
|
||||
initializer: None,
|
||||
is_const: false,
|
||||
});
|
||||
}
|
||||
Ok(CType::UnnamedStruct(c_fields))
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ impl StatementsTranspiler {
|
|||
name: name.clone(),
|
||||
ty,
|
||||
initializer,
|
||||
is_const: false,
|
||||
};
|
||||
|
||||
(name, decl)
|
||||
|
|
@ -182,6 +183,7 @@ impl StatementsTranspiler {
|
|||
name: name.clone(),
|
||||
ty: c_type,
|
||||
initializer,
|
||||
is_const: false,
|
||||
};
|
||||
Ok(CStmt::VarDecl(var_decl))
|
||||
}
|
||||
|
|
@ -233,6 +235,7 @@ impl StatementsTranspiler {
|
|||
name: var_name.clone(),
|
||||
ty: CType::Int,
|
||||
initializer: Some(start_expr),
|
||||
is_const: false,
|
||||
};
|
||||
|
||||
let cond = CExpr::BinOp(
|
||||
|
|
@ -284,6 +287,7 @@ impl StatementsTranspiler {
|
|||
)),
|
||||
Box::new(CExpr::Var(idx_name.clone())),
|
||||
)),
|
||||
is_const: false,
|
||||
});
|
||||
|
||||
let mut body_stmts = vec![bind];
|
||||
|
|
@ -333,6 +337,7 @@ impl StatementsTranspiler {
|
|||
Box::new(CExpr::Var(arr_name.clone())),
|
||||
Box::new(CExpr::Var(idx_name.clone())),
|
||||
)),
|
||||
is_const: false,
|
||||
});
|
||||
|
||||
let mut body_stmts = vec![bind];
|
||||
|
|
@ -468,6 +473,8 @@ impl StatementsTranspiler {
|
|||
BinOp::Or => Ok(CBinaryOp::Or),
|
||||
BinOp::BitwiseAnd => Ok(CBinaryOp::BitwiseAnd),
|
||||
BinOp::BitwiseOr => Ok(CBinaryOp::BitwiseOr),
|
||||
BinOp::LShift => Ok(CBinaryOp::LShift),
|
||||
BinOp::RShift => Ok(CBinaryOp::RShift),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -481,7 +488,7 @@ impl StatementsTranspiler {
|
|||
}
|
||||
}
|
||||
|
||||
fn type_to_ctype(&self, ty: &Type) -> Result<CType, String> {
|
||||
pub fn type_to_ctype(&self, ty: &Type) -> Result<CType, String> {
|
||||
match ty {
|
||||
Type::Int => Ok(CType::Int),
|
||||
Type::U8 => Ok(CType::U8),
|
||||
|
|
@ -509,6 +516,7 @@ impl StatementsTranspiler {
|
|||
name: format!("field{}", i),
|
||||
ty: c_type,
|
||||
initializer: None,
|
||||
is_const: false,
|
||||
});
|
||||
}
|
||||
Ok(CType::UnnamedStruct(fields))
|
||||
|
|
@ -565,6 +573,7 @@ impl StatementsTranspiler {
|
|||
name: format!("field{}", i),
|
||||
ty: field_type,
|
||||
initializer: None,
|
||||
is_const: false,
|
||||
});
|
||||
}
|
||||
Ok(CType::UnnamedStruct(c_fields))
|
||||
|
|
|
|||
|
|
@ -90,6 +90,39 @@ impl Transpiler {
|
|||
self.lower_declarations_to_c_ir(node)?;
|
||||
}
|
||||
|
||||
// Add builtin structs
|
||||
if !self.structs.iter().any(|s| s.name == "Color") {
|
||||
self.structs.push(CStructDecl {
|
||||
name: "Color".to_string(),
|
||||
fields: vec![
|
||||
CVarDecl { name: "r".to_string(), ty: CType::U8, initializer: None, is_const: false },
|
||||
CVarDecl { name: "g".to_string(), ty: CType::U8, initializer: None, is_const: false },
|
||||
CVarDecl { name: "b".to_string(), ty: CType::U8, initializer: None, is_const: false },
|
||||
CVarDecl { name: "a".to_string(), ty: CType::U8, initializer: None, is_const: false },
|
||||
],
|
||||
});
|
||||
// Generate TypeInfo
|
||||
let bitmap = Self::generate_pointer_bitmap(&vec![
|
||||
CVarDecl { name: "r".to_string(), ty: CType::U8, initializer: None, is_const: false },
|
||||
CVarDecl { name: "g".to_string(), ty: CType::U8, initializer: None, is_const: false },
|
||||
CVarDecl { name: "b".to_string(), ty: CType::U8, initializer: None, is_const: false },
|
||||
CVarDecl { name: "a".to_string(), ty: CType::U8, initializer: None, is_const: false },
|
||||
]);
|
||||
self.typeinfo_map.insert("Color".to_string(), bitmap);
|
||||
}
|
||||
if !self.structs.iter().any(|s| s.name == "Shader") {
|
||||
self.structs.push(CStructDecl {
|
||||
name: "Shader".to_string(),
|
||||
fields: vec![
|
||||
CVarDecl { name: "id".to_string(), ty: CType::Int, initializer: None, is_const: false },
|
||||
],
|
||||
});
|
||||
let bitmap = Self::generate_pointer_bitmap(&vec![
|
||||
CVarDecl { name: "id".to_string(), ty: CType::Int, initializer: None, is_const: false },
|
||||
]);
|
||||
self.typeinfo_map.insert("Shader".to_string(), bitmap);
|
||||
}
|
||||
|
||||
self.lower_function_bodies_to_c_ir(nodes)?;
|
||||
|
||||
// Rename main to suic_main and track that we have a main
|
||||
|
|
@ -238,6 +271,16 @@ impl Transpiler {
|
|||
self.functions.push(func_decl);
|
||||
}
|
||||
}
|
||||
TypedASTNodeKind::Const(c) => {
|
||||
let value_code = self.stmt_transpiler.transpile_expr(&c.value)?;
|
||||
let var_decl = CVarDecl {
|
||||
name: c.name.clone(),
|
||||
ty: self.stmt_transpiler.type_to_ctype(&c.value.ty)?,
|
||||
initializer: Some(value_code),
|
||||
is_const: true,
|
||||
};
|
||||
self.globals.push(var_decl);
|
||||
}
|
||||
TypedASTNodeKind::Extern(e) => {
|
||||
// For externs, we might need to add function prototypes
|
||||
// But for now, skip as they're handled differently
|
||||
|
|
@ -408,6 +451,9 @@ impl Transpiler {
|
|||
CType::FixedArray(elem_ty, size) => format!("{} {}[{}]", elem_ty.to_string(), var.name, size),
|
||||
_ => format!("{} {}", var.ty.to_string(), var.name),
|
||||
};
|
||||
if var.is_const {
|
||||
output = format!("const {}", output);
|
||||
}
|
||||
if let Some(init) = &var.initializer {
|
||||
match (&var.ty, init) {
|
||||
(CType::FixedArray(_, _), CExpr::ArrayLit(elements)) => {
|
||||
|
|
@ -652,13 +698,14 @@ impl Transpiler {
|
|||
"rl_pop_matrix" => "suic_rl_pop_matrix",
|
||||
"rl_translate_f" => "suic_rl_translate_f",
|
||||
"rl_rotate_f" => "suic_rl_rotate_f",
|
||||
// UI Framework Utils
|
||||
"draw_text" => "suic_draw_text",
|
||||
"draw_rectangle" => "suic_draw_rectangle",
|
||||
"draw_rectangle_lines" => "suic_draw_rectangle_lines",
|
||||
"measure_text" => "suic_measure_text",
|
||||
"draw_circle" => "suic_draw_circle",
|
||||
"draw_line" => "suic_draw_line",
|
||||
// UI Framework Utils
|
||||
"draw_text" => "DrawText",
|
||||
"draw_rectangle" => "DrawRectangle",
|
||||
"draw_rectangle_lines" => "DrawRectangleLines",
|
||||
"measure_text" => "MeasureText",
|
||||
"draw_circle" => "DrawCircle",
|
||||
"draw_line" => "DrawLine",
|
||||
"draw_fps" => "DrawFPS",
|
||||
// Player controller functions
|
||||
"player_controller_create" => "suic_player_controller_create",
|
||||
"player_controller_destroy" => "suic_player_controller_destroy",
|
||||
|
|
@ -749,18 +796,7 @@ impl Transpiler {
|
|||
"Vec3" => "suic_vec3".to_string(),
|
||||
_ => format!("struct {}", struct_name),
|
||||
};
|
||||
// For built-in simple structs, generate compound literal directly
|
||||
// For user-defined structs, use heap allocation
|
||||
match struct_name.as_str() {
|
||||
"Vec2" | "Vec3" => format!("({}){{ {} }}", c_type_name, field_inits.join(", ")),
|
||||
_ => format!(
|
||||
"suic_alloc_struct(&sui_typeinfo_{}, sizeof({}), &({}){{ {} }})",
|
||||
struct_name,
|
||||
c_type_name,
|
||||
c_type_name,
|
||||
field_inits.join(", ")
|
||||
),
|
||||
}
|
||||
format!("({}){{ {} }}", c_type_name, field_inits.join(", "))
|
||||
}
|
||||
CExpr::EnumLit(enum_name, variant_name, args) => {
|
||||
// Find the variant index - for simplicity, assume variants are in order
|
||||
|
|
|
|||
|
|
@ -370,14 +370,22 @@ impl ImportResolver {
|
|||
ASTNodeKind::Load(_) => {
|
||||
result.push(node);
|
||||
}
|
||||
ASTNodeKind::Trait(t) => {
|
||||
self.symbol_registry.register(
|
||||
t.name.clone(),
|
||||
filename.to_string(),
|
||||
node.span.clone(),
|
||||
)?;
|
||||
result.push(node);
|
||||
}
|
||||
ASTNodeKind::Trait(t) => {
|
||||
self.symbol_registry.register(
|
||||
t.name.clone(),
|
||||
filename.to_string(),
|
||||
node.span.clone(),
|
||||
)?;
|
||||
result.push(node);
|
||||
}
|
||||
ASTNodeKind::Const(c) => {
|
||||
self.symbol_registry.register(
|
||||
c.name.clone(),
|
||||
filename.to_string(),
|
||||
node.span.clone(),
|
||||
)?;
|
||||
result.push(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -146,6 +146,9 @@ pub enum Token {
|
|||
#[token("trait")]
|
||||
KeywordTrait,
|
||||
|
||||
#[token("const")]
|
||||
KeywordConst,
|
||||
|
||||
// #[token("type")]
|
||||
// KeywordType,
|
||||
//
|
||||
|
|
@ -182,6 +185,12 @@ pub enum Token {
|
|||
#[token("**", priority = 3)]
|
||||
Power,
|
||||
|
||||
#[token("<<")]
|
||||
LShift,
|
||||
|
||||
#[token(">>")]
|
||||
RShift,
|
||||
|
||||
#[token("$")]
|
||||
Dollar,
|
||||
|
||||
|
|
|
|||
|
|
@ -244,6 +244,9 @@ fn run_file(filename: &str, debug: bool) -> Result<(), String> {
|
|||
suicmez::ast::TypedASTNodeKind::Function(f) => {
|
||||
format!("Function({})", f.name)
|
||||
}
|
||||
suicmez::ast::TypedASTNodeKind::Const(c) => {
|
||||
format!("Const({})", c.name)
|
||||
}
|
||||
suicmez::ast::TypedASTNodeKind::Struct(s) => {
|
||||
format!("Struct({}) with {} params", s.name, s.parameters.len())
|
||||
}
|
||||
|
|
@ -297,6 +300,9 @@ fn run_file(filename: &str, debug: bool) -> Result<(), String> {
|
|||
suicmez::ast::TypedASTNodeKind::Function(f) => {
|
||||
format!("Function({})", f.name)
|
||||
}
|
||||
suicmez::ast::TypedASTNodeKind::Const(c) => {
|
||||
format!("Const({})", c.name)
|
||||
}
|
||||
suicmez::ast::TypedASTNodeKind::Struct(s) => {
|
||||
format!("Struct({}) with {} params", s.name, s.parameters.len())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,6 +104,9 @@ impl Monomorphizer {
|
|||
|
||||
for (_idx, node) in nodes.iter().enumerate() {
|
||||
match &node.kind {
|
||||
TypedASTNodeKind::Const(c) => {
|
||||
result_nodes.push(node.clone());
|
||||
}
|
||||
TypedASTNodeKind::Function(f) => {
|
||||
// Skip generic functions - they'll be added as specialized versions when needed
|
||||
if !f.parameters.is_empty() {
|
||||
|
|
@ -988,6 +991,9 @@ fn check_node_for_typevars(node: &TypedASTNode) -> Result<(), MonomorphizationEr
|
|||
TypedASTNodeKind::Function(f) => {
|
||||
check_function_for_typevars(f)?;
|
||||
}
|
||||
TypedASTNodeKind::Const(c) => {
|
||||
// Consts should not have typevars
|
||||
}
|
||||
TypedASTNodeKind::Struct(s) => {
|
||||
check_struct_for_typevars(s)?;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,6 +149,16 @@ impl Parser {
|
|||
attributes,
|
||||
})
|
||||
}
|
||||
Some(Token::KeywordConst) => {
|
||||
self.next();
|
||||
let const_def = self.parse_const()?;
|
||||
let end = self.peek_span().unwrap_or(start..start).end;
|
||||
Ok(ASTNode {
|
||||
kind: ASTNodeKind::Const(const_def),
|
||||
span: Span::new(&(start..end), self.file.clone()),
|
||||
attributes,
|
||||
})
|
||||
}
|
||||
Some(Token::KeywordStruct) => {
|
||||
self.next();
|
||||
let struct_def = self.parse_struct()?;
|
||||
|
|
@ -211,12 +221,33 @@ impl Parser {
|
|||
}
|
||||
Some(token) => {
|
||||
let span = self.peek_span().unwrap_or(start..start);
|
||||
self.error(format!("Unexpected token at top level: {:?}. Expected declarations like 'fn', 'struct', 'enum', 'impl', 'trait', 'use', 'load', or 'extern'", token), span)
|
||||
self.error(format!("Unexpected token at top level: {:?}. Expected declarations like 'fn', 'struct', 'enum', 'impl', 'trait', 'const', 'use', 'load', or 'extern'", token), span)
|
||||
}
|
||||
None => self.error("Unexpected end of file at top level. Expected declarations like 'fn', 'struct', 'enum', etc.".to_string(), start..start),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_const(&mut self) -> Result<Const, ParseError> {
|
||||
let start = self.peek_span().unwrap_or(0..0).start;
|
||||
let name = match self.next() {
|
||||
Some((Token::Variable(n), _)) => n,
|
||||
Some((_, span)) => return self.error("Expected constant name after 'const' keyword. Example: const PI = 3.14".to_string(), span),
|
||||
None => return self.error("Expected constant name after 'const' keyword. Example: const PI = 3.14".to_string(), start..start),
|
||||
};
|
||||
|
||||
let typ = if matches!(self.peek(), Some(Token::Colon)) {
|
||||
self.next();
|
||||
Some(self.parse_type_annot()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
self.expect(Token::Assign)?;
|
||||
let value = self.parse_expr()?;
|
||||
|
||||
Ok(Const { name, typ, value })
|
||||
}
|
||||
|
||||
fn parse_attribute(&mut self) -> Result<Attribute, ParseError> {
|
||||
self.expect(Token::At)?;
|
||||
let start = self.peek_span().unwrap_or(0..0).start;
|
||||
|
|
@ -1173,14 +1204,44 @@ impl Parser {
|
|||
Ok(left)
|
||||
}
|
||||
|
||||
fn parse_bitwise_and_expr(&mut self) -> Result<Expr, ParseError> {
|
||||
fn parse_shift_expr(&mut self) -> Result<Expr, ParseError> {
|
||||
let mut left = self.parse_eq_expr()?;
|
||||
|
||||
loop {
|
||||
let op = if matches!(self.peek(), Some(Token::LShift)) {
|
||||
Some(BinOp::LShift)
|
||||
} else if matches!(self.peek(), Some(Token::RShift)) {
|
||||
Some(BinOp::RShift)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if let Some(op) = op {
|
||||
let start = left.span.start;
|
||||
self.next();
|
||||
let right = self.parse_eq_expr()?;
|
||||
let end = right.span.end;
|
||||
left = Expr {
|
||||
kind: ExprKind::BinOp(Box::new(left), op, Box::new(right)),
|
||||
span: Span::new(&(start..end), self.file.clone()),
|
||||
attributes: Vec::new(),
|
||||
};
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(left)
|
||||
}
|
||||
|
||||
fn parse_bitwise_and_expr(&mut self) -> Result<Expr, ParseError> {
|
||||
let mut left = self.parse_shift_expr()?;
|
||||
|
||||
loop {
|
||||
if matches!(self.peek(), Some(Token::BitAnd)) {
|
||||
let start = left.span.start;
|
||||
self.next();
|
||||
let right = self.parse_eq_expr()?;
|
||||
let right = self.parse_shift_expr()?;
|
||||
let end = right.span.end;
|
||||
left = Expr {
|
||||
kind: ExprKind::BinOp(Box::new(left), BinOp::BitwiseAnd, Box::new(right)),
|
||||
|
|
|
|||
|
|
@ -370,6 +370,351 @@ impl TypeChecker {
|
|||
}
|
||||
|
||||
fn add_builtin_functions(&mut self) {
|
||||
// Builtin types
|
||||
self.env.types.insert(
|
||||
"Vector3".to_string(),
|
||||
TypeInfo {
|
||||
kind: TypeInfoKind::Struct(vec![
|
||||
("x".to_string(), TypeAnnot::Var("float".to_string())),
|
||||
("y".to_string(), TypeAnnot::Var("float".to_string())),
|
||||
("z".to_string(), TypeAnnot::Var("float".to_string())),
|
||||
]),
|
||||
parameters: vec![],
|
||||
},
|
||||
);
|
||||
self.env.types.insert(
|
||||
"Color".to_string(),
|
||||
TypeInfo {
|
||||
kind: TypeInfoKind::Struct(vec![
|
||||
("r".to_string(), TypeAnnot::Var("u8".to_string())),
|
||||
("g".to_string(), TypeAnnot::Var("u8".to_string())),
|
||||
("b".to_string(), TypeAnnot::Var("u8".to_string())),
|
||||
("a".to_string(), TypeAnnot::Var("u8".to_string())),
|
||||
]),
|
||||
parameters: vec![],
|
||||
},
|
||||
);
|
||||
self.env.types.insert(
|
||||
"Shader".to_string(),
|
||||
TypeInfo {
|
||||
kind: TypeInfoKind::Struct(vec![
|
||||
("id".to_string(), TypeAnnot::Var("int".to_string())),
|
||||
]),
|
||||
parameters: vec![],
|
||||
},
|
||||
);
|
||||
self.env.types.insert(
|
||||
"Vector2".to_string(),
|
||||
TypeInfo {
|
||||
kind: TypeInfoKind::Struct(vec![
|
||||
("x".to_string(), TypeAnnot::Var("float".to_string())),
|
||||
("y".to_string(), TypeAnnot::Var("float".to_string())),
|
||||
]),
|
||||
parameters: vec![],
|
||||
},
|
||||
);
|
||||
self.env.types.insert(
|
||||
"sockaddr_in".to_string(),
|
||||
TypeInfo {
|
||||
kind: TypeInfoKind::Struct(vec![
|
||||
("sin_family".to_string(), TypeAnnot::Var("u16".to_string())),
|
||||
("sin_port".to_string(), TypeAnnot::Var("u16".to_string())),
|
||||
("sin_addr".to_string(), TypeAnnot::Cons("in_addr".to_string(), vec![])),
|
||||
("sin_zero".to_string(), TypeAnnot::FixedArray(Box::new(TypeAnnot::Var("u8".to_string())), 8)),
|
||||
]),
|
||||
parameters: vec![],
|
||||
},
|
||||
);
|
||||
|
||||
// Builtin functions
|
||||
// Raylib
|
||||
self.env.functions.insert(
|
||||
"init_window".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Int, Type::Int, Type::String],
|
||||
return_type: Type::Unit,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"close_window".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![],
|
||||
return_type: Type::Unit,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"window_should_close".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![],
|
||||
return_type: Type::Bool,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"set_target_fps".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Int],
|
||||
return_type: Type::Unit,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"disable_cursor".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![],
|
||||
return_type: Type::Unit,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"get_char_pressed".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![],
|
||||
return_type: Type::Int,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"is_key_pressed".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Int],
|
||||
return_type: Type::Bool,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"is_key_down".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Int],
|
||||
return_type: Type::Bool,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"get_mouse_delta".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![],
|
||||
return_type: Type::Struct("Vector2".to_string(), vec![]),
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"is_mouse_button_down".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Int],
|
||||
return_type: Type::Bool,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"get_random_value".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Int, Type::Int],
|
||||
return_type: Type::Int,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"get_frame_time".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![],
|
||||
return_type: Type::Float,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"begin_drawing".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![],
|
||||
return_type: Type::Unit,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"end_drawing".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![],
|
||||
return_type: Type::Unit,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"clear_background".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Int, Type::Int, Type::Int, Type::Int],
|
||||
return_type: Type::Unit,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"draw_text".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::String, Type::Int, Type::Int, Type::Int, Type::Int, Type::Int, Type::Int, Type::Int],
|
||||
return_type: Type::Unit,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"draw_fps".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Int, Type::Int],
|
||||
return_type: Type::Unit,
|
||||
},
|
||||
);
|
||||
|
||||
// Math functions
|
||||
self.env.functions.insert(
|
||||
"sinf".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Float],
|
||||
return_type: Type::Float,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"cosf".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Float],
|
||||
return_type: Type::Float,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"sqrtf".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Float],
|
||||
return_type: Type::Float,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"fmaxf".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Float, Type::Float],
|
||||
return_type: Type::Float,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"floorf".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Float],
|
||||
return_type: Type::Float,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"powf".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Float, Type::Float],
|
||||
return_type: Type::Float,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"expf".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Float],
|
||||
return_type: Type::Float,
|
||||
},
|
||||
);
|
||||
|
||||
// Noise functions
|
||||
self.env.functions.insert(
|
||||
"grad2".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Int, Type::Float, Type::Float],
|
||||
return_type: Type::Float,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"simplex_noise_2d".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Float, Type::Float],
|
||||
return_type: Type::Float,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"fbm_noise".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Float, Type::Float, Type::Int],
|
||||
return_type: Type::Float,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"get_terrain_height".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Float, Type::Float],
|
||||
return_type: Type::Float,
|
||||
},
|
||||
);
|
||||
|
||||
// Socket functions
|
||||
self.env.functions.insert(
|
||||
"socket".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Int, Type::Int, Type::Int],
|
||||
return_type: Type::Int,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"sendto".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Int, Type::Ptr(Box::new(Type::U8)), Type::Int, Type::Int, Type::Ptr(Box::new(Type::Unit)), Type::Int],
|
||||
return_type: Type::Int,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"recvfrom".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Int, Type::Ptr(Box::new(Type::U8)), Type::Int, Type::Int, Type::Ptr(Box::new(Type::Unit)), Type::Ptr(Box::new(Type::Int))],
|
||||
return_type: Type::Int,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"close".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Int],
|
||||
return_type: Type::Int,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"htonl".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Int],
|
||||
return_type: Type::Int,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"htons".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Int],
|
||||
return_type: Type::Int,
|
||||
},
|
||||
);
|
||||
self.env.functions.insert(
|
||||
"inet_pton".to_string(),
|
||||
FunctionType {
|
||||
type_params: vec![],
|
||||
params: vec![Type::Int, Type::String, Type::Ptr(Box::new(Type::Unit))],
|
||||
return_type: Type::Int,
|
||||
},
|
||||
);
|
||||
|
||||
// ODE Physics Engine functions
|
||||
self.env.functions.insert(
|
||||
"ode_init".to_string(),
|
||||
|
|
@ -1564,6 +1909,19 @@ impl TypeChecker {
|
|||
|
||||
fn typecheck_node(&mut self, node: &ASTNode) -> Result<TypedASTNode, TypeError> {
|
||||
let ty = match &node.kind {
|
||||
ASTNodeKind::Const(c) => {
|
||||
let typed_value = self.typecheck_expr(&c.value)?;
|
||||
return Ok(TypedASTNode {
|
||||
kind: TypedASTNodeKind::Const(TypedConst {
|
||||
name: c.name.clone(),
|
||||
typ: c.typ.clone(),
|
||||
value: typed_value.clone(),
|
||||
}),
|
||||
span: node.span.clone(),
|
||||
attributes: node.attributes.clone(),
|
||||
ty: typed_value.ty,
|
||||
});
|
||||
}
|
||||
ASTNodeKind::Function(f) => {
|
||||
let typed_func = self.typecheck_function(f)?;
|
||||
let ty = typed_func.ty.clone();
|
||||
|
|
@ -1862,7 +2220,7 @@ impl TypeChecker {
|
|||
let typed_right = self.typecheck_expr(right)?;
|
||||
|
||||
let result_type = match op {
|
||||
BinOp::Add | BinOp::Sub | BinOp::Mul | BinOp::Div | BinOp::Mod | BinOp::BitwiseAnd | BinOp::BitwiseOr => {
|
||||
BinOp::Add | BinOp::Sub | BinOp::Mul | BinOp::Div | BinOp::Mod | BinOp::BitwiseAnd | BinOp::BitwiseOr | BinOp::LShift | BinOp::RShift => {
|
||||
if !self.types_compatible(&typed_left.ty, &typed_right.ty) {
|
||||
return Err(TypeError {
|
||||
kind: TypeErrorKind::TypeMismatch(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue