Skip to content

Commit

Permalink
[WIP] Parse AnyMethodCall, start trying to compile
Browse files Browse the repository at this point in the history
  • Loading branch information
cosine authored and CosineP committed Apr 5, 2022
1 parent 9bb03ee commit 40e0985
Show file tree
Hide file tree
Showing 15 changed files with 91 additions and 38 deletions.
6 changes: 6 additions & 0 deletions integration_tests/test_data/any_method.notwasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
function main(): i32 {
var a = any(@array_new());
var _ = a?.push<(Array) -> i32, (str) -> i32>(undefined);
var r = 5;
return r;
}
Empty file.
1 change: 0 additions & 1 deletion libjankscripten/src/jankyscript/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ pub mod constructors;
pub mod from_js;
mod fv;
mod insert_returns;
mod methods;
mod operators;
mod operators_z3;
mod pretty;
Expand Down
2 changes: 1 addition & 1 deletion libjankscripten/src/jankyscript/select_method_call.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
//! Turn (typed) method calls into relevant typed calls
use super::constructors::*;
use super::methods::get_type_by_prefix;
use super::syntax::*;
use super::walk::*;
use crate::rts_function::RTSFunction;
use crate::shared::methods::get_type_by_prefix;
use crate::typ;

/// Turn (typed) method calls into relevant typed calls
Expand Down
2 changes: 1 addition & 1 deletion libjankscripten/src/jankyscript/type_checking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
//! This occurs after type inference to ensure that type inference succeeded
//! correctly.
use super::methods::get_type_by_prefix;
use super::syntax::*;
use crate::pos::Pos;
use crate::shared::methods::get_type_by_prefix;
use crate::shared::std_lib::get_global_object;
use im_rc::HashMap;
use thiserror::Error;
Expand Down
2 changes: 1 addition & 1 deletion libjankscripten/src/jankyscript/typeinf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@
//! list of types.
use super::super::shared::coercions::Coercion;
use super::methods::METHODS_TABLE;
use super::operators::OVERLOADS;
use super::operators_z3::Z3Operators;
use super::syntax::*;
use super::typeinf_env::Env;
use super::walk::{Loc, Visitor};
use crate::pos::Pos;
use crate::shared::methods::METHODS_TABLE;
use crate::typ;
use crate::z3ez::Z3EZ;
use z3::ast::{self, Ast, Dynamic};
Expand Down
13 changes: 11 additions & 2 deletions libjankscripten/src/notwasm/from_jankyscript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ use super::super::rope::Rope;
use super::constructors::*;
use super::syntax::*;
use crate::pos::Pos;
use crate::rts_function::RTSFunction;
use crate::shared::methods::METHODS_TABLE;
use crate::shared::NameGen;
use std::collections::HashMap;

Expand Down Expand Up @@ -424,10 +424,19 @@ fn compile_expr<'a>(state: &'a mut S, expr: J::Expr, cxt: C<'a>) -> Rope<Stmt> {
state,
*obj,
C::id(move |state, fun_id| {
// borrow checker
let args_len = args.len();
compile_exprs(state, args, move |state, arg_ids| {
let possible_typs = METHODS_TABLE
.get(&(method.as_str(), args_len))
.unwrap()
.iter()
// never a function type
.map(|t| t.notwasm_typ(false))
.collect();
cxt.recv_e(
state,
Expr::AnyMethodCall(fun_id, method, arg_ids, todo!(), p),
Expr::AnyMethodCall(fun_id, method, arg_ids, possible_typs, p),
)
})
}),
Expand Down
1 change: 1 addition & 0 deletions libjankscripten/src/notwasm/lexer.l
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,5 @@ while "while"
\) ")"
\[ "["
\] "]"
\? "?"
. "UNMATCHED"
5 changes: 3 additions & 2 deletions libjankscripten/src/notwasm/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ IdString -> String :
;

Id -> Id :
'ID' { Id::Named($lexer.span_str($1.unwrap().span()).to_string()) }
IdString { Id::Named($1) }
| 'bogus' '(' 'env' ')' { Id::Bogus("env") }
;

Expand Down Expand Up @@ -80,7 +80,7 @@ AtomSeq -> Vec<Atom> :
;

Atom -> Atom :
'$' Id '(' AtomSeq ')' { Atom::PrimApp($2, $4, pos($1)) }
'$' Id '(' AtomSeq ')' { Atom::PrimApp($2, $4, pos($1)) }
| 'any' '(' Atom ')' { Atom::ToAny(ToAny::new($3), pos($1)) }
| 'env' '.' U32 ':' Type { Atom::EnvGet($3, $5, pos($4)) }
| 'rt' '(' Id ')' { Atom::GetPrimFunc($3, pos($1)) }
Expand Down Expand Up @@ -138,6 +138,7 @@ Expr -> Expr :
| 'newRef' '(' Atom ',' Type ')' { Expr::NewRef($3, $5, pos($1)) }
| Id '!' '(' IdSeq ')' { Expr::ClosureCall($1, $4, pos($2)) }
| Id '(' IdSeq ')' { Expr::Call($1, $3, pos($2)) }
| Id '?' '.' IdString '<' TypeSeq '>' '(' IdSeq ')' { Expr::AnyMethodCall($1, $4, $9, $6, pos($3)) }
| AtomAdd { let p = $1.pos().clone(); Expr::Atom($1, p) }
;

Expand Down
24 changes: 17 additions & 7 deletions libjankscripten/src/notwasm/rt_bindings.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::constructors::*;
use super::syntax::Type;
use super::{constructors::*, syntax::FnType};
use crate::rts_function::{RTSFunction, RTSFunctionImpl};
use crate::shared::methods::METHODS_TABLE;
use std::collections::HashMap;
use strum::IntoEnumIterator;
use Type::*;
Expand Down Expand Up @@ -38,21 +39,30 @@ pub fn get_rt_bindings() -> BindMap {
&mono,
vec![I32, Bool, a_clos.clone()],
);
let mut insert_rts_fn = |rts: &RTSFunction| {
if let RTSFunctionImpl::Rust(name) = rts.name() {
// Automatically generate the name and notwasm type
m.insert(name.into(), rts.janky_typ().notwasm_typ(false));
}
};
// Step 2: automatically insert runtime functions from RTSFunction.
for rts in RTSFunction::iter() {
match rts {
RTSFunction::Todo(..) | RTSFunction::Import(..) | RTSFunction::Method(..) => (),
_ => {
if let RTSFunctionImpl::Rust(name) = rts.name() {
// Automatically generate the name and notwasm type
m.insert(name.into(), rts.janky_typ().notwasm_typ(false));
}
}
_ => insert_rts_fn(&rts),
}

// NotWasm runtime functions do not need to be added because
// NotWasm already knows about them.
}
// Step 3: RTSFunction::Method is infinitely large, import only the ones
// created by METHODS_TABLE
for ((name, _), typs) in METHODS_TABLE.iter() {
for typ in typs {
let rts = RTSFunction::Method(name.to_string(), typ.clone());
insert_rts_fn(&rts);
}
}
map
}

Expand Down
60 changes: 37 additions & 23 deletions libjankscripten/src/notwasm/translation.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
//! translate NotWasm to wasm, using the rust runtime whenever possible
//!
//! preconditions: [super::compile]
//!
//! Much of this module relies on constants duplicated in the runtime, of
//! course. Check the constants at the top of the file, and any comments that refer
//! to other definitions
use super::super::rts_function::*;
use super::rt_bindings::get_rt_bindings;
Expand All @@ -21,6 +25,9 @@ const ANY_SIZE: u32 = 8;
const TAG_SIZE: u32 = 4;
const LENGTH_SIZE: u32 = 4;
const FN_OBJ_SIZE: u32 = 4;
// Check runtime::any_value::test::abi_any_discriminants_stable. For now, (my version of) rust seems to have stable and sensible discriminants for our any representation, which is defined by rust. Then we USE these assumptions in translation for:
// Expr::AnyMethodCall
// Expr::AnyLength (TODO)

type FuncTypeMap = HashMap<(Vec<ValueType>, Option<ValueType>), u32>;

Expand Down Expand Up @@ -709,35 +716,42 @@ impl<'a> Translate<'a> {
_ => panic!("expected Func ID ({})", f),
};
}
// This is using assumptions from the runtime. See
// runtime::any_value::test::abi_any_discriminants_stable
N::Expr::AnyMethodCall(obj, method, args, typs, s) => {
todo!();
// Unconditional exit 8 (acting 5)
self.out.push(Block(BlockType::Value(ValueType::I64)));
// Error 7 (acting 4)
self.out.push(Block(BlockType::Value(ValueType::I64)));
// Skip null 6
// Skip undefined 5
// TODO(closure) 4
// Ptr 3
self.out.push(Block(BlockType::Value(ValueType::I64)));
// Bool 2
self.out.push(Block(BlockType::Value(ValueType::I64)));
// F64 1
self.out.push(Block(BlockType::Value(ValueType::I64)));
// I32 0
self.out.push(Block(BlockType::Value(ValueType::I64)));
// Get our object and look at the descriminant
// Does this get the discriminant?? Idk!
self.get_id(obj);
self.out.push(I32Const(0xf000));
self.out.push(I32And);
self.out.push(I32Const(3 * 8));
self.out.push(I32ShrU);
// See runtime::any_value::tests::abi_any_discriminants_stable
BrTable(Box::new(BrTableData {
table: Box::new([0, 1, 2, 3, 4, 5, 6]),
default: 7,
}));
todo!()
self.to_any(&N::Type::I32);
self.rt_call("dbg_log");
//// Unconditional exit 8 (acting 5)
//self.out.push(Block(BlockType::Value(ValueType::I64)));
//// Error 7 (acting 4)
//self.out.push(Block(BlockType::Value(ValueType::I64)));
//// Skip null 6
//// Skip undefined 5
//// TODO(closure) 4
//// Ptr 3
//self.out.push(Block(BlockType::Value(ValueType::I64)));
//// Bool 2
//self.out.push(Block(BlockType::Value(ValueType::I64)));
//// F64 1
//self.out.push(Block(BlockType::Value(ValueType::I64)));
//// I32 0
//self.out.push(Block(BlockType::Value(ValueType::I64)));
//// Get our object and look at the discriminant
//self.get_id(obj);
//self.out.push(I32Const(0xf000));
//self.out.push(I32And);
//self.out.push(I32Const(3 * 8));
//self.out.push(I32ShrU);
//BrTable(Box::new(BrTableData {
// table: Box::new([0, 1, 2, 3, 4, 5, 6]),
// default: 7,
//}));
}
N::Expr::ClosureCall(f, args, s) => {
match self.id_env.get(f).cloned() {
Expand Down
File renamed without changes.
1 change: 1 addition & 0 deletions libjankscripten/src/shared/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod coercions;
mod id;
pub mod methods;
pub mod std_lib;
mod types;

Expand Down
11 changes: 11 additions & 0 deletions runtime/src/wasm32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,17 @@ pub fn log_any_raw(_this: AnyValue, any: AnyValue) -> AnyValue {
AnyEnum::I32(42).into()
}

/// *This cannot be called by notwasm*. However it is extremely useful for
/// debugging / notwasm compilation because it doesn't require extra arguments
/// dbg_log returns its input so as long as the top of the stack is an any, it
/// can be inserted *anywhere*
#[no_mangle]
pub fn dbg_log(any: AnyValue) -> AnyValue {
let real: AnyEnum = *any;
log!("{:?}", real);
any
}

pub fn heap() -> &'static Heap {
unsafe { &HEAP }.as_ref().unwrap()
}
1 change: 1 addition & 0 deletions stdlib.notwasm
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import math_max : (env, any, any, any) -> any;
// __JNKS
import heap_dump : (env, any) -> any;
import log_any_raw : (any, any) -> any;
//import dbg_log : (any) -> any;

import janky_primitive_plus : (any, any) -> any;
import any_is_object : (any) -> bool;
Expand Down

0 comments on commit 40e0985

Please sign in to comment.