Initial function prototype (no arguments yet)
This commit is contained in:
parent
15d1d627fd
commit
98354eb44f
5 changed files with 127 additions and 62 deletions
46
Cargo.lock
generated
46
Cargo.lock
generated
|
@ -13,9 +13,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.56"
|
version = "1.0.57"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27"
|
checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ascii-canvas"
|
name = "ascii-canvas"
|
||||||
|
@ -78,16 +78,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "3.1.8"
|
version = "3.1.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "71c47df61d9e16dc010b55dba1952a57d8c215dbb533fd13cdd13369aac73b1c"
|
checksum = "7c167e37342afc5f33fd87bbc870cedd020d2a6dffa05d45ccd9241fbdd146db"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atty",
|
"atty",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
|
"clap_lex",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"os_str_bytes",
|
|
||||||
"strsim",
|
"strsim",
|
||||||
"termcolor",
|
"termcolor",
|
||||||
"textwrap",
|
"textwrap",
|
||||||
|
@ -106,6 +106,15 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "189ddd3b5d32a70b35e7686054371742a937b0d99128e76dde6340210e966669"
|
||||||
|
dependencies = [
|
||||||
|
"os_str_bytes",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crunchy"
|
name = "crunchy"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
|
@ -216,7 +225,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "inkwell"
|
name = "inkwell"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/TheDan64/inkwell?branch=master#36c3b106e61b1b45295a35f94023d93d9328c76f"
|
source = "git+https://github.com/TheDan64/inkwell?branch=master#bff378bee02bcbb5bed35f47e9ed69e6642e9188"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"either",
|
"either",
|
||||||
"inkwell_internals",
|
"inkwell_internals",
|
||||||
|
@ -229,7 +238,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "inkwell_internals"
|
name = "inkwell_internals"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
source = "git+https://github.com/TheDan64/inkwell?branch=master#36c3b106e61b1b45295a35f94023d93d9328c76f"
|
source = "git+https://github.com/TheDan64/inkwell?branch=master#bff378bee02bcbb5bed35f47e9ed69e6642e9188"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -285,15 +294,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.121"
|
version = "0.2.124"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f"
|
checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "llvm-sys"
|
name = "llvm-sys"
|
||||||
version = "120.2.3"
|
version = "120.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ce76f8393b7a607a906087666db398d872db739622e644e58552c198ccdfdf45"
|
checksum = "09b716322964966a62377cf86e64f00ca7043505fdf27bd2ec7d41ae6682d1e7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
@ -344,9 +353,6 @@ name = "os_str_bytes"
|
||||||
version = "6.0.0"
|
version = "6.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
|
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
|
@ -437,18 +443,18 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.36"
|
version = "1.0.37"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
|
checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.17"
|
version = "1.0.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58"
|
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
@ -553,9 +559,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.90"
|
version = "1.0.91"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "704df27628939572cd88d33f171cd6f896f4eaca85252c6e0a72d8d8287ee86f"
|
checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
|
@ -6,7 +6,10 @@ use inkwell::{
|
||||||
context::Context,
|
context::Context,
|
||||||
module::Module,
|
module::Module,
|
||||||
types::{BasicMetadataTypeEnum, BasicTypeEnum, FunctionType},
|
types::{BasicMetadataTypeEnum, BasicTypeEnum, FunctionType},
|
||||||
values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, BasicMetadataValueEnum},
|
values::{
|
||||||
|
BasicMetadataValueEnum, BasicValueEnum, FunctionValue, IntValue,
|
||||||
|
PointerValue,
|
||||||
|
},
|
||||||
IntPredicate,
|
IntPredicate,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -81,10 +84,9 @@ impl Expr<Type> {
|
||||||
ty: func_ty,
|
ty: func_ty,
|
||||||
kind: EnvValueKind::Func(func_ptr),
|
kind: EnvValueKind::Func(func_ptr),
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
fn DUMB_CONVERT(a: BasicValueEnum) -> BasicMetadataValueEnum {
|
fn DUMB_CONVERT(a: BasicValueEnum) -> BasicMetadataValueEnum {
|
||||||
use BasicValueEnum as A;
|
|
||||||
use BasicMetadataValueEnum as B;
|
use BasicMetadataValueEnum as B;
|
||||||
|
use BasicValueEnum as A;
|
||||||
match a {
|
match a {
|
||||||
A::ArrayValue(a) => B::ArrayValue(a),
|
A::ArrayValue(a) => B::ArrayValue(a),
|
||||||
A::IntValue(a) => B::IntValue(a),
|
A::IntValue(a) => B::IntValue(a),
|
||||||
|
@ -97,15 +99,16 @@ impl Expr<Type> {
|
||||||
|
|
||||||
let args_llvm = args
|
let args_llvm = args
|
||||||
.iter()
|
.iter()
|
||||||
.map(|arg| {
|
.map(|arg| arg.into_llvm(context, builder, env).map(DUMB_CONVERT))
|
||||||
arg.into_llvm(context, builder, env).map(DUMB_CONVERT)
|
|
||||||
})
|
|
||||||
.collect::<Result<Vec<_>>>()?;
|
.collect::<Result<Vec<_>>>()?;
|
||||||
|
|
||||||
builder.build_call(*func_ptr, args_llvm.as_slice(), "");
|
let call_site =
|
||||||
|
builder.build_call(*func_ptr, args_llvm.as_slice(), "");
|
||||||
|
|
||||||
todo!()
|
let value = call_site.try_as_basic_value().unwrap_left();
|
||||||
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => bail!("No function with name {func:?}"),
|
_ => bail!("No function with name {func:?}"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -277,19 +280,39 @@ pub fn convert(
|
||||||
let module = context.create_module(&file_name);
|
let module = context.create_module(&file_name);
|
||||||
let builder = context.create_builder();
|
let builder = context.create_builder();
|
||||||
|
|
||||||
|
let mut env = Env::default();
|
||||||
for func in program.iter().filter_map(|decl| match decl {
|
for func in program.iter().filter_map(|decl| match decl {
|
||||||
Decl::Func(v) => Some(v),
|
Decl::Func(v) => Some(v),
|
||||||
_ => None,
|
_ => None,
|
||||||
}) {
|
}) {
|
||||||
let return_ty = func.return_ty.into_llvm_basic_type(context);
|
let return_ty = func.return_ty.into_llvm_basic_type(context);
|
||||||
let llvm_func_ty = fn_type_basic(return_ty, &[], false);
|
let llvm_func_ty = fn_type_basic(return_ty, &[], false);
|
||||||
|
|
||||||
let llvm_func = module.add_function(&func.name, llvm_func_ty, None);
|
let llvm_func = module.add_function(&func.name, llvm_func_ty, None);
|
||||||
|
|
||||||
|
env.local_type_map.insert(
|
||||||
|
func.name.clone(),
|
||||||
|
EnvValue {
|
||||||
|
ty: &func.ty,
|
||||||
|
kind: EnvValueKind::Func(llvm_func),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for func in program.iter().filter_map(|decl| match decl {
|
||||||
|
Decl::Func(v) => Some(v),
|
||||||
|
_ => None,
|
||||||
|
}) {
|
||||||
|
let llvm_func = match env.local_type_map.get(&func.name) {
|
||||||
|
Some(EnvValue {
|
||||||
|
kind: EnvValueKind::Func(func),
|
||||||
|
..
|
||||||
|
}) => func.clone(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
let entry_block = context.append_basic_block(llvm_func, "entry");
|
let entry_block = context.append_basic_block(llvm_func, "entry");
|
||||||
|
|
||||||
builder.position_at_end(entry_block);
|
builder.position_at_end(entry_block);
|
||||||
|
|
||||||
let env = Env::default();
|
|
||||||
convert_stmts(&context, &module, &llvm_func, &builder, &env, &func.stmts)?;
|
convert_stmts(&context, &module, &llvm_func, &builder, &env, &func.stmts)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ pub struct Func<T> {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub return_ty: Type,
|
pub return_ty: Type,
|
||||||
pub stmts: Vec<Stmt<T>>,
|
pub stmts: Vec<Stmt<T>>,
|
||||||
|
pub ty: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::{
|
||||||
|
collections::{HashMap, HashSet},
|
||||||
|
mem,
|
||||||
|
};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
|
@ -73,7 +76,7 @@ impl Op {
|
||||||
#[derive(Debug, Hash, Eq, PartialEq)]
|
#[derive(Debug, Hash, Eq, PartialEq)]
|
||||||
struct Constraint(Type_, Type_);
|
struct Constraint(Type_, Type_);
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Debug, Default)]
|
||||||
struct Env {
|
struct Env {
|
||||||
parent: Option<Box<Env>>,
|
parent: Option<Box<Env>>,
|
||||||
local_type_map: HashMap<String, Type_>,
|
local_type_map: HashMap<String, Type_>,
|
||||||
|
@ -145,7 +148,7 @@ impl<'a> AnnotationContext<'a> {
|
||||||
fn annotate_stmts(
|
fn annotate_stmts(
|
||||||
ctx: &mut AnnotationContext,
|
ctx: &mut AnnotationContext,
|
||||||
stmts: impl AsRef<[Stmt<()>]>,
|
stmts: impl AsRef<[Stmt<()>]>,
|
||||||
) -> Vec<Stmt<Type_>> {
|
) -> Result<Vec<Stmt<Type_>>> {
|
||||||
let stmts = stmts.as_ref();
|
let stmts = stmts.as_ref();
|
||||||
let mut new_stmts = Vec::new();
|
let mut new_stmts = Vec::new();
|
||||||
ctx.push_scope();
|
ctx.push_scope();
|
||||||
|
@ -153,14 +156,16 @@ fn annotate_stmts(
|
||||||
for stmt in stmts.iter() {
|
for stmt in stmts.iter() {
|
||||||
match stmt {
|
match stmt {
|
||||||
Stmt::Return(ret_val) => {
|
Stmt::Return(ret_val) => {
|
||||||
let new_stmt =
|
let new_stmt = match ret_val {
|
||||||
Stmt::Return(ret_val.as_ref().map(|expr| annotate_expr(ctx, expr)));
|
Some(v) => Some(annotate_expr(ctx, v)?),
|
||||||
new_stmts.push(new_stmt);
|
None => None,
|
||||||
|
};
|
||||||
|
new_stmts.push(Stmt::Return(new_stmt));
|
||||||
}
|
}
|
||||||
|
|
||||||
Stmt::Let(name, ty, body) => {
|
Stmt::Let(name, ty, body) => {
|
||||||
let new_stmt =
|
let new_stmt =
|
||||||
Stmt::Let(name.clone(), ty.clone(), annotate_expr(ctx, body));
|
Stmt::Let(name.clone(), ty.clone(), annotate_expr(ctx, body)?);
|
||||||
let ty = match ty {
|
let ty = match ty {
|
||||||
Some(v) => Type_::from_type(v.clone()),
|
Some(v) => Type_::from_type(v.clone()),
|
||||||
None => ctx.type_var(),
|
None => ctx.type_var(),
|
||||||
|
@ -170,18 +175,21 @@ fn annotate_stmts(
|
||||||
}
|
}
|
||||||
|
|
||||||
Stmt::IfElse(if_else) => {
|
Stmt::IfElse(if_else) => {
|
||||||
let new_stmt = Stmt::IfElse(annotate_if_else(ctx, &if_else));
|
let new_stmt = Stmt::IfElse(annotate_if_else(ctx, &if_else)?);
|
||||||
new_stmts.push(new_stmt);
|
new_stmts.push(new_stmt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.pop_scope();
|
ctx.pop_scope();
|
||||||
new_stmts
|
Ok(new_stmts)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn annotate_expr(ctx: &mut AnnotationContext, expr: &Expr<()>) -> Expr<Type_> {
|
fn annotate_expr(
|
||||||
match &expr.kind {
|
ctx: &mut AnnotationContext,
|
||||||
|
expr: &Expr<()>,
|
||||||
|
) -> Result<Expr<Type_>> {
|
||||||
|
Ok(match &expr.kind {
|
||||||
ExprKind::Int(n) => Expr {
|
ExprKind::Int(n) => Expr {
|
||||||
kind: ExprKind::Int(*n),
|
kind: ExprKind::Int(*n),
|
||||||
ty: Type_::Int,
|
ty: Type_::Int,
|
||||||
|
@ -199,8 +207,8 @@ fn annotate_expr(ctx: &mut AnnotationContext, expr: &Expr<()>) -> Expr<Type_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprKind::BinOp(left, op, right) => {
|
ExprKind::BinOp(left, op, right) => {
|
||||||
let left = annotate_expr(ctx, left);
|
let left = annotate_expr(ctx, left)?;
|
||||||
let right = annotate_expr(ctx, right);
|
let right = annotate_expr(ctx, right)?;
|
||||||
let output = ctx.type_var();
|
let output = ctx.type_var();
|
||||||
|
|
||||||
op.constraints(ctx, &left.ty, &right.ty, &output);
|
op.constraints(ctx, &left.ty, &right.ty, &output);
|
||||||
|
@ -211,63 +219,84 @@ fn annotate_expr(ctx: &mut AnnotationContext, expr: &Expr<()>) -> Expr<Type_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprKind::Call(func, args) => {
|
ExprKind::Call(func_name, args) => {
|
||||||
let mut args_annot = Vec::new();
|
let mut args_annot = Vec::new();
|
||||||
let ret_ty = ctx.type_var();
|
let ret_ty = ctx.type_var();
|
||||||
|
|
||||||
|
let (func_args_ty, func_ret_ty) =
|
||||||
|
match ctx.current_env.as_ref().unwrap().lookup(func_name) {
|
||||||
|
Some(Type_::Func(args, ret)) => (args.clone(), *ret.clone()),
|
||||||
|
Some(_) => bail!("Not a function"),
|
||||||
|
None => bail!("Name not found"),
|
||||||
|
};
|
||||||
|
|
||||||
|
ctx.constrain(ret_ty.clone(), func_ret_ty);
|
||||||
|
|
||||||
for arg in args {
|
for arg in args {
|
||||||
let arg_annot = annotate_expr(ctx, arg);
|
let arg_annot = annotate_expr(ctx, arg)?;
|
||||||
args_annot.push(arg_annot);
|
args_annot.push(arg_annot);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr {
|
Expr {
|
||||||
kind: ExprKind::Call(func.to_string(), args_annot),
|
kind: ExprKind::Call(func_name.to_string(), args_annot),
|
||||||
ty: ret_ty,
|
ty: ret_ty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn annotate_if_else(
|
fn annotate_if_else(
|
||||||
ctx: &mut AnnotationContext,
|
ctx: &mut AnnotationContext,
|
||||||
if_else: &IfElse<()>,
|
if_else: &IfElse<()>,
|
||||||
) -> IfElse<Type_> {
|
) -> Result<IfElse<Type_>> {
|
||||||
let converted_cond = annotate_expr(ctx, &if_else.cond);
|
let converted_cond = annotate_expr(ctx, &if_else.cond)?;
|
||||||
let converted_body = annotate_stmts(ctx, &if_else.body);
|
let converted_body = annotate_stmts(ctx, &if_else.body)?;
|
||||||
|
|
||||||
let else_clause = match &if_else.else_clause {
|
let else_clause = match &if_else.else_clause {
|
||||||
Some(ElseClause::If(if_else2)) => {
|
Some(ElseClause::If(if_else2)) => {
|
||||||
Some(ElseClause::If(Box::new(annotate_if_else(ctx, &if_else2))))
|
Some(ElseClause::If(Box::new(annotate_if_else(ctx, &if_else2)?)))
|
||||||
}
|
}
|
||||||
Some(ElseClause::Body(stmts)) => {
|
Some(ElseClause::Body(stmts)) => {
|
||||||
Some(ElseClause::Body(annotate_stmts(ctx, &stmts)))
|
Some(ElseClause::Body(annotate_stmts(ctx, &stmts)?))
|
||||||
}
|
}
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
IfElse {
|
Ok(IfElse {
|
||||||
cond: converted_cond,
|
cond: converted_cond,
|
||||||
body: converted_body,
|
body: converted_body,
|
||||||
else_clause,
|
else_clause,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_info(func: &Func<()>) -> (Func<Type_>, HashSet<Constraint>) {
|
fn collect_info(
|
||||||
|
env: Env,
|
||||||
|
func: &Func<()>,
|
||||||
|
) -> Result<(Func<Type_>, HashSet<Constraint>, Env)> {
|
||||||
let mut constraints = HashSet::new();
|
let mut constraints = HashSet::new();
|
||||||
let mut ctx = AnnotationContext {
|
let mut ctx = AnnotationContext {
|
||||||
counter: 0,
|
counter: 0,
|
||||||
constraints: &mut constraints,
|
constraints: &mut constraints,
|
||||||
current_env: Some(Env::default()),
|
current_env: Some(env),
|
||||||
};
|
};
|
||||||
let new_stmts = annotate_stmts(&mut ctx, &func.stmts);
|
let new_stmts = annotate_stmts(&mut ctx, &func.stmts)?;
|
||||||
|
|
||||||
|
// TODO: Args
|
||||||
|
let total_ty = Type_::Func(
|
||||||
|
Vec::new(),
|
||||||
|
Box::new(Type_::from_type(func.return_ty.clone())),
|
||||||
|
);
|
||||||
|
|
||||||
let func = Func {
|
let func = Func {
|
||||||
name: func.name.clone(),
|
name: func.name.clone(),
|
||||||
return_ty: func.return_ty.clone(),
|
return_ty: func.return_ty.clone(),
|
||||||
stmts: new_stmts,
|
stmts: new_stmts,
|
||||||
|
ty: total_ty,
|
||||||
};
|
};
|
||||||
|
|
||||||
(func, constraints)
|
let env = ctx.current_env.unwrap();
|
||||||
|
mem::drop(ctx.constraints);
|
||||||
|
Ok((func, constraints, env))
|
||||||
}
|
}
|
||||||
|
|
||||||
type Assignments = HashMap<usize, Type_>;
|
type Assignments = HashMap<usize, Type_>;
|
||||||
|
@ -420,28 +449,34 @@ fn substitute_in_func(
|
||||||
name: func.name,
|
name: func.name,
|
||||||
return_ty: func.return_ty,
|
return_ty: func.return_ty,
|
||||||
stmts: substitute_in_stmts(assignments, func.stmts)?,
|
stmts: substitute_in_stmts(assignments, func.stmts)?,
|
||||||
|
ty: func.ty.convert(assignments)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn convert(ast: Vec<Decl<()>>) -> Result<Vec<Decl<Type>>> {
|
pub fn convert(ast: Vec<Decl<()>>) -> Result<Vec<Decl<Type>>> {
|
||||||
// First pass, gather all of the type signatures in the top level
|
// First pass, gather all of the type signatures in the top level
|
||||||
let mut top_level_signatures = HashMap::new();
|
let mut top_level_env = Env::default();
|
||||||
for decl in ast.iter() {
|
for decl in ast.iter() {
|
||||||
match decl {
|
match decl {
|
||||||
super::Decl::Func(func) => {
|
super::Decl::Func(func) => {
|
||||||
let name = func.name.clone();
|
let name = func.name.clone();
|
||||||
let ty = Type::Func(Vec::new(), Box::new(func.return_ty.clone()));
|
let ty = Type::Func(Vec::new(), Box::new(func.return_ty.clone()));
|
||||||
top_level_signatures.insert(name, ty);
|
top_level_env
|
||||||
|
.local_type_map
|
||||||
|
.insert(name, Type_::from_type(ty));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now, type-check each function separately
|
// Now, type-check each function separately
|
||||||
let mut new_decl = Vec::new();
|
let mut new_decl = Vec::new();
|
||||||
|
let mut env = top_level_env;
|
||||||
for decl in ast.iter() {
|
for decl in ast.iter() {
|
||||||
match decl {
|
match decl {
|
||||||
Decl::Func(func) => {
|
Decl::Func(func) => {
|
||||||
let (decorated_func, constraints) = collect_info(func);
|
println!("Processing func {:?}", func);
|
||||||
|
let (decorated_func, constraints, env2) = collect_info(env, func)?;
|
||||||
|
env = env2;
|
||||||
println!("func: {:?}", decorated_func);
|
println!("func: {:?}", decorated_func);
|
||||||
println!("constraints: {:?}", constraints);
|
println!("constraints: {:?}", constraints);
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ Decl: Decl<()> = {
|
||||||
|
|
||||||
Func: Func<()> = {
|
Func: Func<()> = {
|
||||||
"fn" <name:Ident> "(" ")" "->" <return_ty:Type> "{" <stmts:Stmt*> "}" =>
|
"fn" <name:Ident> "(" ")" "->" <return_ty:Type> "{" <stmts:Stmt*> "}" =>
|
||||||
Func { name, return_ty, stmts },
|
Func { name, return_ty, stmts, ty: (), },
|
||||||
};
|
};
|
||||||
|
|
||||||
Stmt: Stmt<()> = {
|
Stmt: Stmt<()> = {
|
||||||
|
|
Loading…
Reference in a new issue