added support for function imports

This commit is contained in:
2021-11-03 22:07:55 +01:00
parent 4f70a65866
commit 4793c4eb69
11 changed files with 101 additions and 21 deletions

View File

@@ -29,7 +29,7 @@ pub enum ImportType {
type_: Type,
mutable: bool,
},
// Function { name: String, params: Vec<Type>, result: Option<Type> }
Function { name: String, params: Vec<Type>, result: Option<Type> }
}
#[derive(Debug)]

View File

@@ -24,6 +24,7 @@ pub fn emit(script: &ast::Script) -> Vec<u8> {
}
let mut globals: HashMap<&str, u32> = HashMap::new();
let mut function_map = HashMap::new();
{
let mut imports = ImportSection::new();
@@ -56,6 +57,18 @@ pub fn emit(script: &ast::Script) -> Vec<u8> {
}
.into()
}
ast::ImportType::Function {
ref name,
ref params,
ref result,
} => {
function_map.insert(name.clone(), function_map.len() as u32);
EntityType::Function(
*function_types
.get(&(params.clone(), result.clone()))
.unwrap() as u32,
)
}
};
imports.import(module, name, type_);
}
@@ -68,16 +81,15 @@ pub fn emit(script: &ast::Script) -> Vec<u8> {
let mut exports = ExportSection::new();
let mut code = CodeSection::new();
let mut function_map = HashMap::new();
for func in script.functions.iter() {
function_map.insert(func.name.clone(), function_map.len() as u32);
}
for (index, func) in script.functions.iter().enumerate() {
for func in script.functions.iter() {
let type_ = *function_types.get(&function_type_key(func)).unwrap();
functions.function(type_ as u32);
if func.export {
exports.export(&func.name, Export::Function(index as u32));
exports.export(&func.name, Export::Function(*function_map.get(&func.name).unwrap() as u32));
}
code.function(&emit_function(func, &globals, &function_map));
@@ -96,11 +108,23 @@ type FunctionTypeKey = (Vec<ast::Type>, Option<ast::Type>);
fn collect_function_types(script: &ast::Script) -> HashMap<FunctionTypeKey, usize> {
let mut types: HashMap<FunctionTypeKey, usize> = HashMap::new();
for import in &script.imports {
if let ast::ImportType::Function {
ref params,
ref result,
..
} = import.type_
{
let index = types.len();
types
.entry((params.clone(), result.clone()))
.or_insert(index);
}
}
for func in &script.functions {
let index = types.len();
types
.entry(function_type_key(func))
.or_insert_with(|| index);
types.entry(function_type_key(func)).or_insert(index);
}
types

View File

@@ -706,9 +706,27 @@ fn top_level_item_parser() -> impl Parser<Token, ast::TopLevelItem, Error = Simp
type_,
});
let import_function = just(Token::Fn)
.ignore_then(identifier.clone())
.then(
type_parser()
.separated_by(just(Token::Ctrl(',')))
.delimited_by(Token::Ctrl('('), Token::Ctrl(')')),
)
.then(
just(Token::Op("->".to_string()))
.ignore_then(type_parser())
.or_not(),
)
.map(|((name, params), result)| ast::ImportType::Function {
name,
params,
result,
});
let import = just(Token::Import)
.ignore_then(string)
.then(import_memory.or(import_global))
.then(import_memory.or(import_global).or(import_function))
.then_ignore(just(Token::Ctrl(';')))
.map_with_span(|(import, type_), span| {
ast::TopLevelItem::Import(ast::Import {

View File

@@ -47,7 +47,29 @@ pub fn tc_script(script: &mut ast::Script, source: &str) -> Result<()> {
);
}
}
// ast::ImportType::Function { .. } => todo!(),
ast::ImportType::Function {
ref name,
ref params,
result: ref result_type,
} => {
if let Some(fnc) = context.functions.get(name) {
result = report_duplicate_definition(
"Function already defined",
&import.span,
&fnc.span,
source,
);
} else {
context.functions.insert(
name.clone(),
FunctionType {
span: import.span.clone(),
params: params.clone(),
type_: *result_type,
},
);
}
}
ast::ImportType::Memory(..) => (),
}
}