Skip to content
Snippets Groups Projects
Commit 44578322 authored by Aaron Councilman's avatar Aaron Councilman
Browse files

Merge branch 'juno-type-system' into 'main'

Juno Improvements: type inference and intrinsics

See merge request !33
parents 5e26d102 05c13184
No related branches found
No related tags found
1 merge request!33Juno Improvements: type inference and intrinsics
fn intrinsics1(x : f32, y : f64) -> f64 {
return sqrt!(x) as f64 + sqrt!(y);
}
fn intrinsics2(x : f32, y : f64) -> f64 {
let a : f32 = exp2!(x);
let b : f64 = exp!(y);
let c : i32 = abs!(x as i32);
let d : f64 = sin!(b);
return a as f64 * d + c as f64;
}
fn poly<f : float, i : number>(x : f, y : i) -> f {
return powf!(x, x) * abs!(y) as f;
}
fn intrinsics3(x : f32, y : u32) -> f32 {
return poly(x, y);
}
......@@ -496,8 +496,24 @@ impl CodeGenerator<'_> {
(read_id, block)
},
Expr::Intrinsic { .. } => {
todo!("intrinsic function codegen")
Expr::Intrinsic { id, ty_args : _, args, .. } => {
// Code gen for each argument in order
let mut block = cur_block;
let mut arg_vals = vec![];
for arg in args {
let (val, new_block)
= self.codegen_expr(arg, types, ssa, func_id, block);
block = new_block;
arg_vals.push(val);
}
// Create the intrinsic call expression
let mut call = self.builder.allocate_node(func_id);
let call_id = call.id();
call.build_intrinsic(*id, arg_vals.into());
let _ = self.builder.add_node(call);
(call_id, block)
},
}
}
......
/* Definitions of the set of intrinsic functions in Juno */
use phf::phf_map;
use crate::types::{Type, TypeSolver};
use crate::types::{Type, TypeSolver, Primitive};
use crate::parser;
// How intrinsics are identified in the Hercules IR
pub type IntrinsicIdentity = usize;
pub type IntrinsicIdentity = hercules_ir::ir::Intrinsic;
// Information about a single intrinsic, including its type information and how it will be
// identified in the Hercules IR
......@@ -13,24 +13,179 @@ pub type IntrinsicIdentity = usize;
pub struct IntrinsicInfo {
pub id : IntrinsicIdentity,
pub kinds : &'static [parser::Kind],
pub args : fn(&Vec<Type>, &mut TypeSolver) -> Vec<(Type, bool)>,
pub ret_typ : fn(&Vec<Type>, &mut TypeSolver) -> Type,
pub typ : fn(&Vec<Type>, &mut TypeSolver) -> (Vec<Type>, Type),
}
fn sqrt_args(ty_args : &Vec<Type>, _ : &mut TypeSolver) -> Vec<(Type, bool)> {
vec![(ty_args[0], false)]
// The type for a function which takes one argument of a variable type and
// returns a value of that same type
fn var_type(ty_args : &Vec<Type>, _ : &mut TypeSolver) -> (Vec<Type>, Type) {
(vec![ty_args[0]], ty_args[0])
}
fn sqrt_return(ty_args : &Vec<Type>, _ : &mut TypeSolver) -> Type {
ty_args[0]
// Type type for a function which takes two arguments of the same variable type
// and returns a value of that same type
fn var2_type(ty_args : &Vec<Type>, _ : &mut TypeSolver) -> (Vec<Type>, Type) {
(vec![ty_args[0], ty_args[0]], ty_args[0])
}
fn pow_type(ty_args : &Vec<Type>, types : &mut TypeSolver) -> (Vec<Type>, Type) {
(vec![ty_args[0], types.new_primitive(Primitive::U32)], ty_args[0])
}
fn powi_type(ty_args : &Vec<Type>, types : &mut TypeSolver) -> (Vec<Type>, Type) {
(vec![ty_args[0], types.new_primitive(Primitive::I32)], ty_args[0])
}
static INTRINSICS : phf::Map<&'static str, IntrinsicInfo> = phf_map! {
"sqrt" => IntrinsicInfo {
id : 0,
"abs" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Abs,
kinds : &[parser::Kind::Number],
args : sqrt_args,
ret_typ : sqrt_return,
typ : var_type,
},
"acos" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::ACos,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"acosh" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::ACosh,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"asin" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::ASin,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"asinh" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::ASinh,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"atan" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::ATan,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"atan2" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::ATan2,
kinds : &[parser::Kind::Float],
typ : var2_type,
},
"atanh" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::ATanh,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"cbrt" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Cbrt,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"ceil" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Ceil,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"cos" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Cos,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"cosh" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Cos,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"exp" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Exp,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"exp2" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Exp2,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"exp_m1" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::ExpM1,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"floor" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Floor,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"ln" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Ln,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"ln_1p" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Ln1P,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"log" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Log,
kinds : &[parser::Kind::Float],
typ : var2_type,
},
"log10" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Log10,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"log2" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Log2,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"pow" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Pow,
kinds : &[parser::Kind::Integer],
typ : pow_type,
},
"powf" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Powf,
kinds : &[parser::Kind::Float],
typ : var2_type,
},
"powi" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Powi,
kinds : &[parser::Kind::Float],
typ : powi_type,
},
"round" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Round,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"sin" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Sin,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"sinh" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Sinh,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"sqrt" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Sqrt,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"tan" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Tan,
kinds : &[parser::Kind::Float],
typ : var_type,
},
"tanh" => IntrinsicInfo {
id : hercules_ir::ir::Intrinsic::Tanh,
kinds : &[parser::Kind::Float],
typ : var_type,
},
};
......
......@@ -22,6 +22,7 @@ const "const"
continue "continue"
else "else"
false "false"
float "float"
fn "fn"
for "for"
if "if"
......@@ -124,7 +125,7 @@ _ "_"
0x[0-9a-fA-F]+ "HEX_INT"
0b[0-1]+ "BIN_INT"
0o[0-7]+ "OCT_INT"
[0-9]+\.[0-9]*(|e[0-9]+) "FLOAT"
[0-9]+\.[0-9]*(|e[0-9]+) "FLOAT_LIT"
. "UNMATCHED"
. "UNARY"
%start Program
%token UNARY
%avoid_insert "FUNC_ATTR" "DOT_NUM" "ID" "INT" "HEX_INT" "BIN_INT" "OCT_INT" "FLOAT"
%avoid_insert "FUNC_ATTR" "DOT_NUM" "ID" "INT" "HEX_INT" "BIN_INT" "OCT_INT" "FLOAT_LIT"
%expect-unused Unmatched 'UNMATCHED' 'UNARY'
%nonassoc ')'
......@@ -81,6 +81,7 @@ Kind -> Result<Kind, ()>
| 'usize' { Ok(Kind::USize) }
| 'number' { Ok(Kind::Number) }
| 'integer' { Ok(Kind::Integer) }
| 'float' { Ok(Kind::Float) }
;
TypeDecl -> Result<Top, ()>
......@@ -111,12 +112,14 @@ ObjField -> Result<ObjField, ()>
Type -> Result<Type, ()>
: PrimType
{ Ok(Type::PrimType{ span : $span, typ : $1? }) }
| '_'
{ Ok(Type::WildType{ span : $span }) }
| '(' Types ')'
{ Ok(Type::TupleType{ span : $span, tys : $2? }) }
| PackageName
{ Ok(Type::NamedType{ span : $span, name : $1?, args : vec![] }) }
{ Ok(Type::NamedType{ span : $span, name : $1?, args : None }) }
| PackageName '::' '<' TypeExprs '>'
{ Ok(Type::NamedType{ span : $span, name : $1?, args : $4? }) }
{ Ok(Type::NamedType{ span : $span, name : $1?, args : Some($4?) }) }
| Type '[' TypeExprs ']'
{ Ok(Type::ArrayType{ span : $span, elem : Box::new($1?), dims : $3? }) }
;
......@@ -289,9 +292,9 @@ Stmt -> Result<Stmt, ()>
| Stmts
{ $1 }
| PackageName '(' Params ')' ';'
{ Ok(Stmt::CallStmt{ span : $span, name : $1?, ty_args : vec![], args : $3? }) }
{ Ok(Stmt::CallStmt{ span : $span, name : $1?, ty_args : None, args : $3? }) }
| PackageName '::' '<' TypeExprs '>' '(' Params ')' ';'
{ Ok(Stmt::CallStmt{ span : $span, name : $1?, ty_args : $4?, args : $7? }) }
{ Ok(Stmt::CallStmt{ span : $span, name : $1?, ty_args : Some($4?), args : $7? }) }
;
Stmts -> Result<Stmt, ()>
: '{' StmtList '}' { Ok(Stmt::BlockStmt{ span : $span, body : $2? }) };
......@@ -370,9 +373,9 @@ Expr -> Result<Expr, ()>
| '(' Exprs ')'
{ Ok(Expr::Tuple{ span : $span, exprs : $2? }) }
| PackageName '{' IdExprs '}'
{ Ok(Expr::Struct{ span : $span, name : $1?, ty_args : vec![], exprs : $3? }) }
{ Ok(Expr::Struct{ span : $span, name : $1?, ty_args : None, exprs : $3? }) }
| PackageName '::' '<' TypeExprs '>' '{' IdExprs '}'
{ Ok(Expr::Struct{ span : $span, name : $1?, ty_args : $4?, exprs : $7? }) }
{ Ok(Expr::Struct{ span : $span, name : $1?, ty_args : Some($4?), exprs : $7? }) }
| 'true'
{ Ok(Expr::BoolLit{ span : $span, value : true }) }
| 'false'
......@@ -380,7 +383,7 @@ Expr -> Result<Expr, ()>
| IntLit
{ let (span, base) = $1?;
Ok(Expr::IntLit{ span : span, base : base }) }
| 'FLOAT'
| 'FLOAT_LIT'
{ Ok(Expr::FloatLit{ span : $span }) }
| '-' Expr %prec 'UNARY'
{ Ok(Expr::UnaryExpr{ span : $span, op : UnaryOp::Negation, expr : Box::new($2?)}) }
......@@ -429,13 +432,13 @@ Expr -> Result<Expr, ()>
| 'if' Expr 'then' Expr 'else' Expr
{ Ok(Expr::CondExpr{ span: $span, cond : Box::new($2?), thn : Box::new($4?), els : Box::new($6?) })}
| PackageName '(' Params ')'
{ Ok(Expr::CallExpr{ span : $span, name : $1?, ty_args : vec![], args: $3? }) }
{ Ok(Expr::CallExpr{ span : $span, name : $1?, ty_args : None, args: $3? }) }
| PackageName '::' '<' TypeExprs '>' '(' Params ')'
{ Ok(Expr::CallExpr{ span : $span, name : $1?, ty_args : $4?, args: $7? }) }
{ Ok(Expr::CallExpr{ span : $span, name : $1?, ty_args : Some($4?), args: $7? }) }
| PackageName '!' '(' Params ')'
{ Ok(Expr::IntrinsicExpr{ span : $span, name : $1?, ty_args : vec![], args: $4? }) }
{ Ok(Expr::IntrinsicExpr{ span : $span, name : $1?, ty_args : None, args: $4? }) }
| PackageName '!' '::' '<' TypeExprs '>' '(' Params ')'
{ Ok(Expr::IntrinsicExpr{ span : $span, name : $1?, ty_args : $5?, args: $8? }) }
{ Ok(Expr::IntrinsicExpr{ span : $span, name : $1?, ty_args : Some($5?), args: $8? }) }
;
IdExprs -> Result<Vec<(Id, Expr)>, ()>
: 'ID' '=' Expr { Ok(vec![(span_of_tok($1)?, $3?)]) }
......@@ -477,7 +480,7 @@ NonStructExpr -> Result<Expr, ()>
| IntLit
{ let (span, base) = $1?;
Ok(Expr::IntLit{ span : span, base : base }) }
| 'FLOAT'
| 'FLOAT_LIT'
{ Ok(Expr::FloatLit{ span : $span }) }
| '-' NonStructExpr %prec 'UNARY'
{ Ok(Expr::UnaryExpr{ span : $span, op : UnaryOp::Negation, expr : Box::new($2?)}) }
......@@ -526,9 +529,9 @@ NonStructExpr -> Result<Expr, ()>
| 'if' NonStructExpr 'then' NonStructExpr 'else' NonStructExpr
{ Ok(Expr::CondExpr{ span: $span, cond : Box::new($2?), thn : Box::new($4?), els : Box::new($6?) })}
| PackageName '(' Params ')'
{ Ok(Expr::CallExpr{ span : $span, name : $1?, ty_args : vec![], args: $3? }) }
{ Ok(Expr::CallExpr{ span : $span, name : $1?, ty_args : None, args: $3? }) }
| PackageName '::' '<' TypeExprs '>' '(' Params ')'
{ Ok(Expr::CallExpr{ span : $span, name : $1?, ty_args : $4?, args: $7? }) }
{ Ok(Expr::CallExpr{ span : $span, name : $1?, ty_args : Some($4?), args: $7? }) }
;
TypeExprs -> Result<Vec<TypeExpr>, ()>
......@@ -543,12 +546,14 @@ TypeExprsS -> Result<Vec<TypeExpr>, ()>
TypeExpr -> Result<TypeExpr, ()>
: PrimType
{ Ok(TypeExpr::PrimType{ span : $span, typ : $1? }) }
| '_'
{ Ok(TypeExpr::WildcardType { span : $span }) }
| '(' TypeExprs ')'
{ Ok(TypeExpr::TupleType{ span : $span, tys : $2? }) }
| PackageName
{ Ok(TypeExpr::NamedTypeExpr{ span : $span, name : $1?, args : vec![]}) }
{ Ok(TypeExpr::NamedTypeExpr{ span : $span, name : $1?, args : None}) }
| PackageName '::' '<' TypeExprs '>'
{ Ok(TypeExpr::NamedTypeExpr{ span : $span, name : $1?, args : $4? }) }
{ Ok(TypeExpr::NamedTypeExpr{ span : $span, name : $1?, args : Some($4?) }) }
| TypeExpr '[' TypeExprs ']'
{ Ok(TypeExpr::ArrayTypeExpr{ span : $span, elem : Box::new($1?), dims : $3? }) }
| IntLit
......@@ -599,7 +604,7 @@ pub type PackageName = Vec<Span>;
pub type ImportName = (PackageName, Option<Span>); // option is the wildcard *
#[derive(Debug, Copy, Clone)]
pub enum Kind { Type, USize, Number, Integer }
pub enum Kind { Type, USize, Number, Integer, Float }
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Primitive { Bool, I8, U8, I16, U16, I32, U32, I64, U64, USize, F32, F64, Void }
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
......@@ -643,8 +648,9 @@ pub enum TyDef {
#[derive(Debug)]
pub enum Type {
PrimType { span : Span, typ : Primitive },
WildType { span : Span },
TupleType { span : Span, tys : Vec<Type> },
NamedType { span : Span, name : PackageName, args : Vec<TypeExpr> },
NamedType { span : Span, name : PackageName, args : Option<Vec<TypeExpr>> },
ArrayType { span : Span, elem : Box<Type>, dims : Vec<TypeExpr> },
}
......@@ -663,7 +669,7 @@ pub enum Stmt {
BreakStmt { span : Span },
ContinueStmt { span : Span },
BlockStmt { span : Span, body : Vec<Stmt> },
CallStmt { span : Span, name : PackageName, ty_args : Vec<TypeExpr>,
CallStmt { span : Span, name : PackageName, ty_args : Option<Vec<TypeExpr>>,
args : Vec<(bool, Expr)> }, // bool indicates & (for inouts)
}
......@@ -692,7 +698,7 @@ pub enum Expr {
NumField { span : Span, lhs : Box<Expr>, rhs : Span },
ArrIndex { span : Span, lhs : Box<Expr>, index : Vec<Expr> },
Tuple { span : Span, exprs : Vec<Expr> },
Struct { span : Span, name : PackageName, ty_args : Vec<TypeExpr>,
Struct { span : Span, name : PackageName, ty_args : Option<Vec<TypeExpr>>,
exprs : Vec<(Id, Expr)> },
BoolLit { span : Span, value : bool },
IntLit { span : Span, base : IntBase },
......@@ -701,17 +707,18 @@ pub enum Expr {
BinaryExpr { span : Span, op : BinaryOp, lhs : Box<Expr>, rhs : Box<Expr> },
CastExpr { span : Span, expr : Box<Expr>, typ : Type },
CondExpr { span : Span, cond : Box<Expr>, thn : Box<Expr>, els : Box<Expr> },
CallExpr { span : Span, name : PackageName, ty_args : Vec<TypeExpr>,
CallExpr { span : Span, name : PackageName, ty_args : Option<Vec<TypeExpr>>,
args : Vec<(bool, Expr)> }, // bool indicates & (for inouts)
IntrinsicExpr { span : Span, name : PackageName, ty_args : Vec<TypeExpr>,
IntrinsicExpr { span : Span, name : PackageName, ty_args : Option<Vec<TypeExpr>>,
args : Vec<(bool, Expr)> },
}
#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum TypeExpr {
PrimType { span : Span, typ : Primitive },
WildcardType { span : Span },
TupleType { span : Span, tys : Vec<TypeExpr> },
NamedTypeExpr { span : Span, name : PackageName, args : Vec<TypeExpr> },
NamedTypeExpr { span : Span, name : PackageName, args : Option<Vec<TypeExpr>> },
ArrayTypeExpr { span : Span, elem : Box<TypeExpr>, dims : Vec<TypeExpr> },
IntLiteral { span : Span, base : IntBase },
Negative { span : Span, expr : Box<TypeExpr> },
......@@ -772,6 +779,7 @@ impl Spans for TypeExpr {
fn span(&self) -> Span {
match self {
TypeExpr::PrimType { span, .. }
| TypeExpr::WildcardType { span, .. }
| TypeExpr::TupleType { span, .. }
| TypeExpr::NamedTypeExpr { span, .. }
| TypeExpr::ArrayTypeExpr { span, .. }
......
use lrlex::DefaultLexerTypes;
use lrpar::NonStreamingLexer;
use cfgrammar::Span;
use std::fmt;
// A location in the program, used in error messages
#[derive(Copy, Clone, Debug)]
pub struct Location {
start_line : usize, start_column : usize,
end_line : usize, end_column : usize,
}
impl Location {
pub fn fake() -> Location {
Location { start_line : 0, start_column : 0,
end_line : 0, end_column : 0 }
}
}
// Conversion from span to internal locations
pub fn span_to_loc(span : Span, lexer : &dyn NonStreamingLexer<DefaultLexerTypes<u32>>)
-> Location {
let ((start_line, start_column), (end_line, end_column)) = lexer.line_col(span);
Location { start_line, start_column, end_line, end_column }
}
// Printing locations
impl fmt::Display for Location {
fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}, {} -- {}, {}",
self.start_line, self.start_column,
self.end_line, self.end_column)
}
}
......@@ -7,6 +7,7 @@ mod dynconst;
mod env;
mod intrinsics;
mod parser;
mod locs;
mod semant;
mod ssa;
mod types;
......
This diff is collapsed.
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment