diff --git a/reid-llvm-lib/src/builder.rs b/reid-llvm-lib/src/builder.rs index d254ec3..6e147fd 100644 --- a/reid-llvm-lib/src/builder.rs +++ b/reid-llvm-lib/src/builder.rs @@ -369,7 +369,7 @@ impl ConstValue { ConstValue::U32(_) => U32, ConstValue::U64(_) => U64, ConstValue::U128(_) => U128, - ConstValue::String(val) => String(val.len() as u32), + ConstValue::String(_) => Ptr(Box::new(I8)), ConstValue::Bool(_) => Bool, } } @@ -390,7 +390,6 @@ impl Type { Type::U128 => true, Type::Bool => true, Type::Void => false, - Type::String(_) => false, Type::Ptr(_) => false, } } @@ -409,7 +408,6 @@ impl Type { Type::U128 => false, Type::Bool => false, Type::Void => false, - Type::String(_) => false, Type::Ptr(_) => false, } } diff --git a/reid-llvm-lib/src/compile.rs b/reid-llvm-lib/src/compile.rs index 7ad7604..4aee881 100644 --- a/reid-llvm-lib/src/compile.rs +++ b/reid-llvm-lib/src/compile.rs @@ -457,9 +457,11 @@ impl ConstValue { ConstValue::U32(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::String(val) => { - LLVMBuildGlobalString(builder, into_cstring(val).as_ptr(), c"string".as_ptr()) - } + ConstValue::String(val) => LLVMBuildGlobalStringPtr( + builder, + into_cstring(val).as_ptr(), + c"string".as_ptr(), + ), } } } @@ -478,7 +480,6 @@ impl Type { Bool => LLVMInt1TypeInContext(context), Void => LLVMVoidType(), Ptr(ty) => LLVMPointerType(ty.as_llvm(context), 0), - String(length) => LLVMArrayType(LLVMInt8TypeInContext(context), *length), } } } diff --git a/reid-llvm-lib/src/lib.rs b/reid-llvm-lib/src/lib.rs index db1351b..eba2147 100644 --- a/reid-llvm-lib/src/lib.rs +++ b/reid-llvm-lib/src/lib.rs @@ -200,7 +200,6 @@ pub enum Type { U128, Bool, Void, - String(u32), Ptr(Box), } diff --git a/reid/src/ast/mod.rs b/reid/src/ast/mod.rs index 1170546..ab28c46 100644 --- a/reid/src/ast/mod.rs +++ b/reid/src/ast/mod.rs @@ -22,6 +22,7 @@ pub enum TypeKind { U32, U64, U128, + String, Array(Box, u64), } @@ -157,6 +158,7 @@ pub enum BlockLevelStatement { #[derive(Debug)] pub enum TopLevelStatement { Import(ImportStatement), + ExternFunction(FunctionSignature), FunctionDefinition(FunctionDefinition), } diff --git a/reid/src/ast/parse.rs b/reid/src/ast/parse.rs index 4b6530f..c861a0e 100644 --- a/reid/src/ast/parse.rs +++ b/reid/src/ast/parse.rs @@ -38,6 +38,7 @@ impl Parse for Type { "u32" => TypeKind::U32, "u64" => TypeKind::U64, "u128" => TypeKind::U128, + "string" => TypeKind::String, _ => Err(stream.expected_err("known type identifier")?)?, } } else { @@ -474,6 +475,13 @@ impl Parse for TopLevelStatement { use TopLevelStatement as Stmt; Ok(match stream.peek() { 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()?), _ => Err(stream.expected_err("import or fn")?)?, }) diff --git a/reid/src/ast/process.rs b/reid/src/ast/process.rs index 7562286..2745378 100644 --- a/reid/src/ast/process.rs +++ b/reid/src/ast/process.rs @@ -42,6 +42,24 @@ impl ast::Module { }; 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 for mir::TypeKind { ast::TypeKind::Array(type_kind, length) => { mir::TypeKind::Array(Box::new(mir::TypeKind::from(*type_kind.clone())), *length) } + ast::TypeKind::String => mir::TypeKind::StringPtr, } } } diff --git a/reid/src/codegen.rs b/reid/src/codegen.rs index 672b83f..8b02f81 100644 --- a/reid/src/codegen.rs +++ b/reid/src/codegen.rs @@ -495,7 +495,7 @@ impl TypeKind { TypeKind::U64 => Type::U64, TypeKind::U128 => Type::U128, 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::Void => Type::Void, TypeKind::Vague(_) => panic!("Tried to compile a vague type!"), diff --git a/reid/src/lexer.rs b/reid/src/lexer.rs index 27283bc..3623dad 100644 --- a/reid/src/lexer.rs +++ b/reid/src/lexer.rs @@ -32,6 +32,8 @@ pub enum Token { True, /// `false` False, + /// `extern` + Extern, // Symbols /// `;` @@ -205,6 +207,7 @@ pub fn tokenize>(to_tokenize: T) -> Result, Error "else" => Token::Else, "true" => Token::True, "false" => Token::False, + "extern" => Token::Extern, _ => Token::Identifier(value), }; variant diff --git a/reid/src/mir/mod.rs b/reid/src/mir/mod.rs index 278e282..2fe9e9d 100644 --- a/reid/src/mir/mod.rs +++ b/reid/src/mir/mod.rs @@ -59,7 +59,7 @@ pub enum TypeKind { #[error("void")] Void, #[error("string")] - String(usize), + StringPtr, #[error("[{0}; {1}]")] Array(Box, u64), #[error(transparent)] @@ -102,7 +102,7 @@ impl TypeKind { TypeKind::U32 => false, TypeKind::U64 => false, TypeKind::U128 => false, - TypeKind::String(_) => false, + TypeKind::StringPtr => false, TypeKind::Array(_, _) => false, } } @@ -123,7 +123,7 @@ impl TypeKind { Bool => true, Vague(_) => false, Void => false, - TypeKind::String(_) => false, + TypeKind::StringPtr => false, Array(_, _) => false, } } @@ -165,7 +165,7 @@ impl Literal { Literal::U64(_) => TypeKind::U64, Literal::U128(_) => TypeKind::U128, Literal::Bool(_) => TypeKind::Bool, - Literal::String(val) => TypeKind::String(val.len()), + Literal::String(_) => TypeKind::StringPtr, Literal::Vague(VagueLiteral::Number(_)) => TypeKind::Vague(VagueType::Number), } } diff --git a/reid/src/mir/typecheck.rs b/reid/src/mir/typecheck.rs index d94c97a..68a2a98 100644 --- a/reid/src/mir/typecheck.rs +++ b/reid/src/mir/typecheck.rs @@ -3,7 +3,7 @@ use std::{convert::Infallible, iter}; use crate::{mir::*, util::try_all}; -use VagueType::*; +use VagueType as Vague; use super::{ pass::{Pass, PassState, ScopeFunction, ScopeVariable, Storage}, @@ -71,7 +71,7 @@ impl FunctionDefinition { for param in &self.parameters { let param_t = state.or_else( param.1.assert_known(), - TypeKind::Vague(Unknown), + TypeKind::Vague(Vague::Unknown), self.signature(), ); let res = state @@ -94,7 +94,9 @@ impl FunctionDefinition { state.scope.return_type_hint = Some(self.return_type.clone()); 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 { @@ -128,12 +130,12 @@ impl Block { // If expression resolution itself was erronous, resolve as // 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 let res_t = state.or_else( res.collapse_into(&var_t_resolved), - TypeKind::Vague(Unknown), + TypeKind::Vague(Vague::Unknown), variable_reference.2 + expression.1, ); @@ -141,7 +143,7 @@ impl Block { // Unable to infer variable type even from expression! Default it let res_t = state.or_else( res_t.or_default(), - TypeKind::Vague(Unknown), + TypeKind::Vague(Vague::Unknown), variable_reference.2, ); @@ -187,13 +189,14 @@ impl Block { // If expression resolution itself was erronous, resolve as // 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 // be the same let res_t = state.or_else( expr_ty.collapse_into(&var.ty.resolve_hinted(&hints)), - TypeKind::Vague(Unknown), + TypeKind::Vague(Vague::Unknown), variable_reference.meta + expression.1, ); @@ -241,7 +244,7 @@ impl Block { let res = expr.typecheck(&mut state, &hints, hint.as_ref()); return Ok(( 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()); Ok(( *return_kind, - state.or_else(res, TypeKind::Vague(Unknown), expr.1), + state.or_else(res, TypeKind::Vague(Vague::Unknown), expr.1), )) } else { Ok((ReturnKind::Soft, TypeKind::Void)) @@ -280,7 +283,7 @@ impl Expression { .map(|var| &var.ty) .cloned() .ok_or(ErrorKind::VariableNotDefined(var_ref.1.clone())), - TypeKind::Vague(Unknown), + TypeKind::Vague(Vague::Unknown), var_ref.2, ) .resolve_hinted(hints); @@ -288,7 +291,7 @@ impl Expression { // Update typing to be more accurate var_ref.0 = state.or_else( var_ref.0.resolve_hinted(hints).collapse_into(&existing), - TypeKind::Vague(Unknown), + TypeKind::Vague(Vague::Unknown), var_ref.2, ); @@ -302,9 +305,9 @@ impl Expression { // TODO make sure lhs and rhs can actually do this binary // operation once relevant 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_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) { // Try to coerce both sides again with collapsed type @@ -343,14 +346,15 @@ impl Expression { let true_params_iter = f .params .into_iter() - .chain(iter::repeat(TypeKind::Vague(Unknown))); + .chain(iter::repeat(TypeKind::Vague(Vague::Unknown))); for (param, true_param_t) in function_call.parameters.iter_mut().zip(true_params_iter) { // Typecheck every param separately 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); } @@ -368,7 +372,7 @@ impl Expression { } ExprKind::If(IfExpression(cond, lhs, rhs)) => { 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); // 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_ret_kind, then_ret_t) = state.or_else( then_res, - (ReturnKind::Soft, TypeKind::Vague(Unknown)), + (ReturnKind::Soft, TypeKind::Vague(Vague::Unknown)), lhs.meta, ); let else_ret_t = if let Some(else_block) = rhs { let res = else_block.typecheck(state, &hints, hint_t); let (else_ret_kind, else_ret_t) = state.or_else( res, - (ReturnKind::Soft, TypeKind::Vague(Unknown)), + (ReturnKind::Soft, TypeKind::Vague(Vague::Unknown)), else_block.meta, ); @@ -437,7 +441,7 @@ impl Expression { } let ty = state.or_else( elem_ty.resolve_hinted(hints).collapse_into(&inferred_ty), - TypeKind::Vague(Unknown), + TypeKind::Vague(Vague::Unknown), self.1, ); *elem_ty = ty.clone(); @@ -477,7 +481,7 @@ impl Expression { Err(errors) => { state.note_errors(errors, self.1); Ok(TypeKind::Array( - Box::new(TypeKind::Vague(Unknown)), + Box::new(TypeKind::Vague(Vague::Unknown)), expressions.len() as u64, )) } @@ -532,16 +536,7 @@ impl Literal { (L::U64(_), TypeKind::U64) => self, (L::U128(_), TypeKind::U128) => self, (L::Bool(_), TypeKind::Bool) => self, - (L::String(val), TypeKind::String(len)) => { - if val.len() == *len { - L::String(val) - } else { - Err(ErrorKind::LiteralIncompatible( - L::String(val), - TypeKind::String(*len), - ))? - } - } + (L::String(val), TypeKind::StringPtr) => self, // TODO make sure that v is actually able to fit in the // requested type (L::Vague(VagueL::Number(v)), TypeKind::I8) => L::I8(v as i8), @@ -575,9 +570,9 @@ impl TypeKind { fn or_default(&self) -> Result { match self { TypeKind::Vague(vague_type) => match &vague_type { - Unknown => Err(ErrorKind::TypeIsVague(*vague_type)), - Number => Ok(TypeKind::I32), - TypeRef(_) => panic!("Hinted default!"), + Vague::Unknown => Err(ErrorKind::TypeIsVague(*vague_type)), + Vague::Number => Ok(TypeKind::I32), + Vague::TypeRef(_) => panic!("Hinted default!"), }, _ => Ok(self.clone()), } @@ -585,7 +580,7 @@ impl TypeKind { fn resolve_hinted(&self, hints: &TypeRefs) -> TypeKind { 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(), }; match resolved { @@ -608,22 +603,24 @@ impl Collapsable for TypeKind { } match (self, other) { - (TypeKind::Vague(Number), other) | (other, TypeKind::Vague(Number)) => match other { - TypeKind::Vague(Unknown) => Ok(TypeKind::Vague(Number)), - TypeKind::Vague(Number) => Ok(TypeKind::Vague(Number)), - TypeKind::I8 - | TypeKind::I16 - | TypeKind::I32 - | TypeKind::I64 - | TypeKind::I128 - | TypeKind::U8 - | TypeKind::U16 - | TypeKind::U32 - | TypeKind::U64 - | TypeKind::U128 => Ok(other.clone()), - _ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())), - }, - (TypeKind::Vague(Unknown), other) | (other, TypeKind::Vague(Unknown)) => { + (TypeKind::Vague(Vague::Number), other) | (other, TypeKind::Vague(Vague::Number)) => { + match other { + TypeKind::Vague(Vague::Unknown) => Ok(TypeKind::Vague(Vague::Number)), + TypeKind::Vague(Vague::Number) => Ok(TypeKind::Vague(Vague::Number)), + TypeKind::I8 + | TypeKind::I16 + | TypeKind::I32 + | TypeKind::I64 + | TypeKind::I128 + | TypeKind::U8 + | TypeKind::U16 + | TypeKind::U32 + | TypeKind::U64 + | TypeKind::U128 => Ok(other.clone()), + _ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())), + } + } + (TypeKind::Vague(Vague::Unknown), other) | (other, TypeKind::Vague(Vague::Unknown)) => { Ok(other.clone()) } _ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())), diff --git a/reid_src/hello_world.reid b/reid_src/hello_world.reid new file mode 100644 index 0000000..c4ee78a --- /dev/null +++ b/reid_src/hello_world.reid @@ -0,0 +1,10 @@ + +extern fn puts(message: string) -> i32; + +fn main() -> u16 { + let hello = "hello world"; + + puts(hello); + + return 0; +}