Remove length param from string, use string pointers instead

This commit is contained in:
Sofia 2025-07-14 18:22:05 +03:00
parent 1173e17fe6
commit 376baa2c9a
11 changed files with 101 additions and 64 deletions

View File

@ -369,7 +369,7 @@ impl ConstValue {
ConstValue::U32(_) => U32, ConstValue::U32(_) => U32,
ConstValue::U64(_) => U64, ConstValue::U64(_) => U64,
ConstValue::U128(_) => U128, ConstValue::U128(_) => U128,
ConstValue::String(val) => String(val.len() as u32), ConstValue::String(_) => Ptr(Box::new(I8)),
ConstValue::Bool(_) => Bool, ConstValue::Bool(_) => Bool,
} }
} }
@ -390,7 +390,6 @@ impl Type {
Type::U128 => true, Type::U128 => true,
Type::Bool => true, Type::Bool => true,
Type::Void => false, Type::Void => false,
Type::String(_) => false,
Type::Ptr(_) => false, Type::Ptr(_) => false,
} }
} }
@ -409,7 +408,6 @@ impl Type {
Type::U128 => false, Type::U128 => false,
Type::Bool => false, Type::Bool => false,
Type::Void => false, Type::Void => false,
Type::String(_) => false,
Type::Ptr(_) => false, Type::Ptr(_) => false,
} }
} }

View File

@ -457,9 +457,11 @@ impl ConstValue {
ConstValue::U32(val) => LLVMConstInt(t, *val as u64, 1), ConstValue::U32(val) => LLVMConstInt(t, *val as u64, 1),
ConstValue::U64(val) => LLVMConstInt(t, *val as u64, 1), ConstValue::U64(val) => LLVMConstInt(t, *val as u64, 1),
ConstValue::U128(val) => LLVMConstInt(t, *val as u64, 1), ConstValue::U128(val) => LLVMConstInt(t, *val as u64, 1),
ConstValue::String(val) => { ConstValue::String(val) => LLVMBuildGlobalStringPtr(
LLVMBuildGlobalString(builder, into_cstring(val).as_ptr(), c"string".as_ptr()) builder,
} into_cstring(val).as_ptr(),
c"string".as_ptr(),
),
} }
} }
} }
@ -478,7 +480,6 @@ impl Type {
Bool => LLVMInt1TypeInContext(context), Bool => LLVMInt1TypeInContext(context),
Void => LLVMVoidType(), Void => LLVMVoidType(),
Ptr(ty) => LLVMPointerType(ty.as_llvm(context), 0), Ptr(ty) => LLVMPointerType(ty.as_llvm(context), 0),
String(length) => LLVMArrayType(LLVMInt8TypeInContext(context), *length),
} }
} }
} }

View File

@ -200,7 +200,6 @@ pub enum Type {
U128, U128,
Bool, Bool,
Void, Void,
String(u32),
Ptr(Box<Type>), Ptr(Box<Type>),
} }

View File

@ -22,6 +22,7 @@ pub enum TypeKind {
U32, U32,
U64, U64,
U128, U128,
String,
Array(Box<TypeKind>, u64), Array(Box<TypeKind>, u64),
} }
@ -157,6 +158,7 @@ pub enum BlockLevelStatement {
#[derive(Debug)] #[derive(Debug)]
pub enum TopLevelStatement { pub enum TopLevelStatement {
Import(ImportStatement), Import(ImportStatement),
ExternFunction(FunctionSignature),
FunctionDefinition(FunctionDefinition), FunctionDefinition(FunctionDefinition),
} }

View File

@ -38,6 +38,7 @@ impl Parse for Type {
"u32" => TypeKind::U32, "u32" => TypeKind::U32,
"u64" => TypeKind::U64, "u64" => TypeKind::U64,
"u128" => TypeKind::U128, "u128" => TypeKind::U128,
"string" => TypeKind::String,
_ => Err(stream.expected_err("known type identifier")?)?, _ => Err(stream.expected_err("known type identifier")?)?,
} }
} else { } else {
@ -474,6 +475,13 @@ impl Parse for TopLevelStatement {
use TopLevelStatement as Stmt; use TopLevelStatement as Stmt;
Ok(match stream.peek() { Ok(match stream.peek() {
Some(Token::ImportKeyword) => Stmt::Import(stream.parse()?), Some(Token::ImportKeyword) => Stmt::Import(stream.parse()?),
Some(Token::Extern) => {
stream.next(); // Consume Extern
stream.expect(Token::FnKeyword)?;
let extern_fn = Stmt::ExternFunction(stream.parse()?);
stream.expect(Token::Semi)?;
extern_fn
}
Some(Token::FnKeyword) => Stmt::FunctionDefinition(stream.parse()?), Some(Token::FnKeyword) => Stmt::FunctionDefinition(stream.parse()?),
_ => Err(stream.expected_err("import or fn")?)?, _ => Err(stream.expected_err("import or fn")?)?,
}) })

View File

@ -42,6 +42,24 @@ impl ast::Module {
}; };
functions.push(def); functions.push(def);
} }
ExternFunction(signature) => {
let def = mir::FunctionDefinition {
name: signature.name.clone(),
return_type: signature
.return_type
.clone()
.map(|r| r.0.into())
.unwrap_or(mir::TypeKind::Void),
parameters: signature
.args
.iter()
.cloned()
.map(|p| (p.0, p.1.into()))
.collect(),
kind: mir::FunctionDefinitionKind::Extern,
};
functions.push(def);
}
} }
} }
@ -226,6 +244,7 @@ impl From<ast::TypeKind> for mir::TypeKind {
ast::TypeKind::Array(type_kind, length) => { ast::TypeKind::Array(type_kind, length) => {
mir::TypeKind::Array(Box::new(mir::TypeKind::from(*type_kind.clone())), *length) mir::TypeKind::Array(Box::new(mir::TypeKind::from(*type_kind.clone())), *length)
} }
ast::TypeKind::String => mir::TypeKind::StringPtr,
} }
} }
} }

View File

@ -495,7 +495,7 @@ impl TypeKind {
TypeKind::U64 => Type::U64, TypeKind::U64 => Type::U64,
TypeKind::U128 => Type::U128, TypeKind::U128 => Type::U128,
TypeKind::Bool => Type::Bool, TypeKind::Bool => Type::Bool,
TypeKind::String(length) => Type::String(*length as u32), TypeKind::StringPtr => Type::Ptr(Box::new(Type::I8)),
TypeKind::Array(elem_t, _) => Type::Ptr(Box::new(elem_t.get_type())), TypeKind::Array(elem_t, _) => Type::Ptr(Box::new(elem_t.get_type())),
TypeKind::Void => Type::Void, TypeKind::Void => Type::Void,
TypeKind::Vague(_) => panic!("Tried to compile a vague type!"), TypeKind::Vague(_) => panic!("Tried to compile a vague type!"),

View File

@ -32,6 +32,8 @@ pub enum Token {
True, True,
/// `false` /// `false`
False, False,
/// `extern`
Extern,
// Symbols // Symbols
/// `;` /// `;`
@ -205,6 +207,7 @@ pub fn tokenize<T: Into<String>>(to_tokenize: T) -> Result<Vec<FullToken>, Error
"else" => Token::Else, "else" => Token::Else,
"true" => Token::True, "true" => Token::True,
"false" => Token::False, "false" => Token::False,
"extern" => Token::Extern,
_ => Token::Identifier(value), _ => Token::Identifier(value),
}; };
variant variant

View File

@ -59,7 +59,7 @@ pub enum TypeKind {
#[error("void")] #[error("void")]
Void, Void,
#[error("string")] #[error("string")]
String(usize), StringPtr,
#[error("[{0}; {1}]")] #[error("[{0}; {1}]")]
Array(Box<TypeKind>, u64), Array(Box<TypeKind>, u64),
#[error(transparent)] #[error(transparent)]
@ -102,7 +102,7 @@ impl TypeKind {
TypeKind::U32 => false, TypeKind::U32 => false,
TypeKind::U64 => false, TypeKind::U64 => false,
TypeKind::U128 => false, TypeKind::U128 => false,
TypeKind::String(_) => false, TypeKind::StringPtr => false,
TypeKind::Array(_, _) => false, TypeKind::Array(_, _) => false,
} }
} }
@ -123,7 +123,7 @@ impl TypeKind {
Bool => true, Bool => true,
Vague(_) => false, Vague(_) => false,
Void => false, Void => false,
TypeKind::String(_) => false, TypeKind::StringPtr => false,
Array(_, _) => false, Array(_, _) => false,
} }
} }
@ -165,7 +165,7 @@ impl Literal {
Literal::U64(_) => TypeKind::U64, Literal::U64(_) => TypeKind::U64,
Literal::U128(_) => TypeKind::U128, Literal::U128(_) => TypeKind::U128,
Literal::Bool(_) => TypeKind::Bool, Literal::Bool(_) => TypeKind::Bool,
Literal::String(val) => TypeKind::String(val.len()), Literal::String(_) => TypeKind::StringPtr,
Literal::Vague(VagueLiteral::Number(_)) => TypeKind::Vague(VagueType::Number), Literal::Vague(VagueLiteral::Number(_)) => TypeKind::Vague(VagueType::Number),
} }
} }

View File

@ -3,7 +3,7 @@
use std::{convert::Infallible, iter}; use std::{convert::Infallible, iter};
use crate::{mir::*, util::try_all}; use crate::{mir::*, util::try_all};
use VagueType::*; use VagueType as Vague;
use super::{ use super::{
pass::{Pass, PassState, ScopeFunction, ScopeVariable, Storage}, pass::{Pass, PassState, ScopeFunction, ScopeVariable, Storage},
@ -71,7 +71,7 @@ impl FunctionDefinition {
for param in &self.parameters { for param in &self.parameters {
let param_t = state.or_else( let param_t = state.or_else(
param.1.assert_known(), param.1.assert_known(),
TypeKind::Vague(Unknown), TypeKind::Vague(Vague::Unknown),
self.signature(), self.signature(),
); );
let res = state let res = state
@ -94,7 +94,9 @@ impl FunctionDefinition {
state.scope.return_type_hint = Some(self.return_type.clone()); state.scope.return_type_hint = Some(self.return_type.clone());
block.typecheck(state, &hints, Some(&return_type)) block.typecheck(state, &hints, Some(&return_type))
} }
FunctionDefinitionKind::Extern => Ok((ReturnKind::Soft, TypeKind::Vague(Unknown))), FunctionDefinitionKind::Extern => {
Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown)))
}
}; };
match inferred { match inferred {
@ -128,12 +130,12 @@ impl Block {
// If expression resolution itself was erronous, resolve as // If expression resolution itself was erronous, resolve as
// Unknown and note error. // Unknown and note error.
let res = state.or_else(res, TypeKind::Vague(Unknown), expression.1); let res = state.or_else(res, TypeKind::Vague(Vague::Unknown), expression.1);
// Make sure the expression and variable type really is the same // Make sure the expression and variable type really is the same
let res_t = state.or_else( let res_t = state.or_else(
res.collapse_into(&var_t_resolved), res.collapse_into(&var_t_resolved),
TypeKind::Vague(Unknown), TypeKind::Vague(Vague::Unknown),
variable_reference.2 + expression.1, variable_reference.2 + expression.1,
); );
@ -141,7 +143,7 @@ impl Block {
// Unable to infer variable type even from expression! Default it // Unable to infer variable type even from expression! Default it
let res_t = state.or_else( let res_t = state.or_else(
res_t.or_default(), res_t.or_default(),
TypeKind::Vague(Unknown), TypeKind::Vague(Vague::Unknown),
variable_reference.2, variable_reference.2,
); );
@ -187,13 +189,14 @@ impl Block {
// If expression resolution itself was erronous, resolve as // If expression resolution itself was erronous, resolve as
// Unknown. // Unknown.
let expr_ty = state.or_else(res, TypeKind::Vague(Unknown), expression.1); let expr_ty =
state.or_else(res, TypeKind::Vague(Vague::Unknown), expression.1);
// Make sure the expression and variable type to really // Make sure the expression and variable type to really
// be the same // be the same
let res_t = state.or_else( let res_t = state.or_else(
expr_ty.collapse_into(&var.ty.resolve_hinted(&hints)), expr_ty.collapse_into(&var.ty.resolve_hinted(&hints)),
TypeKind::Vague(Unknown), TypeKind::Vague(Vague::Unknown),
variable_reference.meta + expression.1, variable_reference.meta + expression.1,
); );
@ -241,7 +244,7 @@ impl Block {
let res = expr.typecheck(&mut state, &hints, hint.as_ref()); let res = expr.typecheck(&mut state, &hints, hint.as_ref());
return Ok(( return Ok((
ReturnKind::Hard, ReturnKind::Hard,
state.or_else(res, TypeKind::Vague(Unknown), expr.1), state.or_else(res, TypeKind::Vague(Vague::Unknown), expr.1),
)); ));
} }
@ -254,7 +257,7 @@ impl Block {
let res = expr.typecheck(&mut state, &hints, ret_hint_t.as_ref()); let res = expr.typecheck(&mut state, &hints, ret_hint_t.as_ref());
Ok(( Ok((
*return_kind, *return_kind,
state.or_else(res, TypeKind::Vague(Unknown), expr.1), state.or_else(res, TypeKind::Vague(Vague::Unknown), expr.1),
)) ))
} else { } else {
Ok((ReturnKind::Soft, TypeKind::Void)) Ok((ReturnKind::Soft, TypeKind::Void))
@ -280,7 +283,7 @@ impl Expression {
.map(|var| &var.ty) .map(|var| &var.ty)
.cloned() .cloned()
.ok_or(ErrorKind::VariableNotDefined(var_ref.1.clone())), .ok_or(ErrorKind::VariableNotDefined(var_ref.1.clone())),
TypeKind::Vague(Unknown), TypeKind::Vague(Vague::Unknown),
var_ref.2, var_ref.2,
) )
.resolve_hinted(hints); .resolve_hinted(hints);
@ -288,7 +291,7 @@ impl Expression {
// Update typing to be more accurate // Update typing to be more accurate
var_ref.0 = state.or_else( var_ref.0 = state.or_else(
var_ref.0.resolve_hinted(hints).collapse_into(&existing), var_ref.0.resolve_hinted(hints).collapse_into(&existing),
TypeKind::Vague(Unknown), TypeKind::Vague(Vague::Unknown),
var_ref.2, var_ref.2,
); );
@ -302,9 +305,9 @@ impl Expression {
// TODO make sure lhs and rhs can actually do this binary // TODO make sure lhs and rhs can actually do this binary
// operation once relevant // operation once relevant
let lhs_res = lhs.typecheck(state, &hints, None); let lhs_res = lhs.typecheck(state, &hints, None);
let lhs_type = state.or_else(lhs_res, TypeKind::Vague(Unknown), lhs.1); let lhs_type = state.or_else(lhs_res, TypeKind::Vague(Vague::Unknown), lhs.1);
let rhs_res = rhs.typecheck(state, &hints, Some(&lhs_type)); let rhs_res = rhs.typecheck(state, &hints, Some(&lhs_type));
let rhs_type = state.or_else(rhs_res, TypeKind::Vague(Unknown), rhs.1); let rhs_type = state.or_else(rhs_res, TypeKind::Vague(Vague::Unknown), rhs.1);
if let Some(collapsed) = state.ok(rhs_type.collapse_into(&rhs_type), self.1) { if let Some(collapsed) = state.ok(rhs_type.collapse_into(&rhs_type), self.1) {
// Try to coerce both sides again with collapsed type // Try to coerce both sides again with collapsed type
@ -343,14 +346,15 @@ impl Expression {
let true_params_iter = f let true_params_iter = f
.params .params
.into_iter() .into_iter()
.chain(iter::repeat(TypeKind::Vague(Unknown))); .chain(iter::repeat(TypeKind::Vague(Vague::Unknown)));
for (param, true_param_t) in for (param, true_param_t) in
function_call.parameters.iter_mut().zip(true_params_iter) function_call.parameters.iter_mut().zip(true_params_iter)
{ {
// Typecheck every param separately // Typecheck every param separately
let param_res = param.typecheck(state, &hints, Some(&true_param_t)); let param_res = param.typecheck(state, &hints, Some(&true_param_t));
let param_t = state.or_else(param_res, TypeKind::Vague(Unknown), param.1); let param_t =
state.or_else(param_res, TypeKind::Vague(Vague::Unknown), param.1);
state.ok(param_t.collapse_into(&true_param_t), param.1); state.ok(param_t.collapse_into(&true_param_t), param.1);
} }
@ -368,7 +372,7 @@ impl Expression {
} }
ExprKind::If(IfExpression(cond, lhs, rhs)) => { ExprKind::If(IfExpression(cond, lhs, rhs)) => {
let cond_res = cond.typecheck(state, &hints, Some(&TypeKind::Bool)); let cond_res = cond.typecheck(state, &hints, Some(&TypeKind::Bool));
let cond_t = state.or_else(cond_res, TypeKind::Vague(Unknown), cond.1); let cond_t = state.or_else(cond_res, TypeKind::Vague(Vague::Unknown), cond.1);
state.ok(cond_t.collapse_into(&TypeKind::Bool), cond.1); state.ok(cond_t.collapse_into(&TypeKind::Bool), cond.1);
// Typecheck then/else return types and make sure they are the // Typecheck then/else return types and make sure they are the
@ -376,14 +380,14 @@ impl Expression {
let then_res = lhs.typecheck(state, &hints, hint_t); let then_res = lhs.typecheck(state, &hints, hint_t);
let (then_ret_kind, then_ret_t) = state.or_else( let (then_ret_kind, then_ret_t) = state.or_else(
then_res, then_res,
(ReturnKind::Soft, TypeKind::Vague(Unknown)), (ReturnKind::Soft, TypeKind::Vague(Vague::Unknown)),
lhs.meta, lhs.meta,
); );
let else_ret_t = if let Some(else_block) = rhs { let else_ret_t = if let Some(else_block) = rhs {
let res = else_block.typecheck(state, &hints, hint_t); let res = else_block.typecheck(state, &hints, hint_t);
let (else_ret_kind, else_ret_t) = state.or_else( let (else_ret_kind, else_ret_t) = state.or_else(
res, res,
(ReturnKind::Soft, TypeKind::Vague(Unknown)), (ReturnKind::Soft, TypeKind::Vague(Vague::Unknown)),
else_block.meta, else_block.meta,
); );
@ -437,7 +441,7 @@ impl Expression {
} }
let ty = state.or_else( let ty = state.or_else(
elem_ty.resolve_hinted(hints).collapse_into(&inferred_ty), elem_ty.resolve_hinted(hints).collapse_into(&inferred_ty),
TypeKind::Vague(Unknown), TypeKind::Vague(Vague::Unknown),
self.1, self.1,
); );
*elem_ty = ty.clone(); *elem_ty = ty.clone();
@ -477,7 +481,7 @@ impl Expression {
Err(errors) => { Err(errors) => {
state.note_errors(errors, self.1); state.note_errors(errors, self.1);
Ok(TypeKind::Array( Ok(TypeKind::Array(
Box::new(TypeKind::Vague(Unknown)), Box::new(TypeKind::Vague(Vague::Unknown)),
expressions.len() as u64, expressions.len() as u64,
)) ))
} }
@ -532,16 +536,7 @@ impl Literal {
(L::U64(_), TypeKind::U64) => self, (L::U64(_), TypeKind::U64) => self,
(L::U128(_), TypeKind::U128) => self, (L::U128(_), TypeKind::U128) => self,
(L::Bool(_), TypeKind::Bool) => self, (L::Bool(_), TypeKind::Bool) => self,
(L::String(val), TypeKind::String(len)) => { (L::String(val), TypeKind::StringPtr) => self,
if val.len() == *len {
L::String(val)
} else {
Err(ErrorKind::LiteralIncompatible(
L::String(val),
TypeKind::String(*len),
))?
}
}
// TODO make sure that v is actually able to fit in the // TODO make sure that v is actually able to fit in the
// requested type // requested type
(L::Vague(VagueL::Number(v)), TypeKind::I8) => L::I8(v as i8), (L::Vague(VagueL::Number(v)), TypeKind::I8) => L::I8(v as i8),
@ -575,9 +570,9 @@ impl TypeKind {
fn or_default(&self) -> Result<TypeKind, ErrorKind> { fn or_default(&self) -> Result<TypeKind, ErrorKind> {
match self { match self {
TypeKind::Vague(vague_type) => match &vague_type { TypeKind::Vague(vague_type) => match &vague_type {
Unknown => Err(ErrorKind::TypeIsVague(*vague_type)), Vague::Unknown => Err(ErrorKind::TypeIsVague(*vague_type)),
Number => Ok(TypeKind::I32), Vague::Number => Ok(TypeKind::I32),
TypeRef(_) => panic!("Hinted default!"), Vague::TypeRef(_) => panic!("Hinted default!"),
}, },
_ => Ok(self.clone()), _ => Ok(self.clone()),
} }
@ -585,7 +580,7 @@ impl TypeKind {
fn resolve_hinted(&self, hints: &TypeRefs) -> TypeKind { fn resolve_hinted(&self, hints: &TypeRefs) -> TypeKind {
let resolved = match self { let resolved = match self {
TypeKind::Vague(TypeRef(idx)) => hints.retrieve_type(*idx).unwrap(), TypeKind::Vague(Vague::TypeRef(idx)) => hints.retrieve_type(*idx).unwrap(),
_ => self.clone(), _ => self.clone(),
}; };
match resolved { match resolved {
@ -608,9 +603,10 @@ impl Collapsable for TypeKind {
} }
match (self, other) { match (self, other) {
(TypeKind::Vague(Number), other) | (other, TypeKind::Vague(Number)) => match other { (TypeKind::Vague(Vague::Number), other) | (other, TypeKind::Vague(Vague::Number)) => {
TypeKind::Vague(Unknown) => Ok(TypeKind::Vague(Number)), match other {
TypeKind::Vague(Number) => Ok(TypeKind::Vague(Number)), TypeKind::Vague(Vague::Unknown) => Ok(TypeKind::Vague(Vague::Number)),
TypeKind::Vague(Vague::Number) => Ok(TypeKind::Vague(Vague::Number)),
TypeKind::I8 TypeKind::I8
| TypeKind::I16 | TypeKind::I16
| TypeKind::I32 | TypeKind::I32
@ -622,8 +618,9 @@ impl Collapsable for TypeKind {
| TypeKind::U64 | TypeKind::U64
| TypeKind::U128 => Ok(other.clone()), | TypeKind::U128 => Ok(other.clone()),
_ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())), _ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())),
}, }
(TypeKind::Vague(Unknown), other) | (other, TypeKind::Vague(Unknown)) => { }
(TypeKind::Vague(Vague::Unknown), other) | (other, TypeKind::Vague(Vague::Unknown)) => {
Ok(other.clone()) Ok(other.clone())
} }
_ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())), _ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())),

10
reid_src/hello_world.reid Normal file
View File

@ -0,0 +1,10 @@
extern fn puts(message: string) -> i32;
fn main() -> u16 {
let hello = "hello world";
puts(hello);
return 0;
}