refactor(starmelon): update v8 dependecy
This commit is contained in:
parent
1c14fc146a
commit
95e21129a8
9 changed files with 894 additions and 338 deletions
|
|
@ -48,7 +48,6 @@ oneshot = "0.1.3"
|
||||||
|
|
||||||
# required for livetable derive macro
|
# required for livetable derive macro
|
||||||
livetable-core = { path = "../../../infra/livetable/core" }
|
livetable-core = { path = "../../../infra/livetable/core" }
|
||||||
cargo-workspace-hack = { version = "0.1", path = "../../../infra/cargo-workspace-hack" }
|
|
||||||
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
||||||
24
elm.json
Normal file
24
elm.json
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"type": "application",
|
||||||
|
"source-directories": [
|
||||||
|
"src/reactor/ui"
|
||||||
|
],
|
||||||
|
"elm-version": "0.19.1",
|
||||||
|
"dependencies": {
|
||||||
|
"direct": {
|
||||||
|
"elm/browser": "1.0.2",
|
||||||
|
"elm/core": "1.0.5",
|
||||||
|
"elm/html": "1.0.0",
|
||||||
|
"elm/time": "1.0.0"
|
||||||
|
},
|
||||||
|
"indirect": {
|
||||||
|
"elm/json": "1.1.3",
|
||||||
|
"elm/url": "1.0.0",
|
||||||
|
"elm/virtual-dom": "1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"test-dependencies": {
|
||||||
|
"direct": {},
|
||||||
|
"indirect": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
module Main exposing (view, view2, view3, view4, view5, view6, view7, view8, badReturnType, true)
|
module Main exposing (view, view2, view3, view4, view5, view6, view7, view8, badReturnType, true, main)
|
||||||
|
|
||||||
import Html exposing (Html, div, text)
|
import Html exposing (Html, div, text)
|
||||||
import Svg exposing (Svg, svg)
|
import Svg exposing (Svg, svg)
|
||||||
|
|
@ -6,6 +6,8 @@ import Array exposing (Array)
|
||||||
import Bytes exposing (Bytes)
|
import Bytes exposing (Bytes)
|
||||||
import Bytes.Decode
|
import Bytes.Decode
|
||||||
|
|
||||||
|
main = text "main"
|
||||||
|
|
||||||
|
|
||||||
type alias Model =
|
type alias Model =
|
||||||
{ a : Int
|
{ a : Int
|
||||||
|
|
|
||||||
187
src/derive/mod.rs
Normal file
187
src/derive/mod.rs
Normal file
|
|
@ -0,0 +1,187 @@
|
||||||
|
use crate::elm;
|
||||||
|
use crate::reporting::{CompilerError, Problem, TypeError};
|
||||||
|
|
||||||
|
use livetable_core::{ColumnDefinition, ColumnType};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use tracing::info_span;
|
||||||
|
|
||||||
|
pub(crate) fn derive_livetable(
|
||||||
|
file: PathBuf,
|
||||||
|
debug: bool,
|
||||||
|
_output: Option<PathBuf>,
|
||||||
|
verbosity: u64,
|
||||||
|
//sqlite_path: Option<PathBuf>,
|
||||||
|
) -> Result<(), Problem> {
|
||||||
|
// Our first elm make call is where we build the users program. There is a pretty good chance
|
||||||
|
// this won't work.
|
||||||
|
elm::make(&file, debug, verbosity)?;
|
||||||
|
|
||||||
|
// Step 2, find the elm.json and elm-stuff directory
|
||||||
|
let elm_project_dir =
|
||||||
|
elm::find_project_root("elm.json", "./").map_err(CompilerError::MissingElmJson)?;
|
||||||
|
|
||||||
|
let elm_cache_dir = elm_project_dir.join("elm-stuff").join("0.19.1");
|
||||||
|
|
||||||
|
if !elm_cache_dir.is_dir() {
|
||||||
|
return Err(CompilerError::MissingElmStuff(elm_cache_dir).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
// step 2.5 get the module name out of the file.
|
||||||
|
let data = std::fs::read(&file)
|
||||||
|
.map_err(|io_err| CompilerError::ReadInputFailed(io_err, file.clone()))?;
|
||||||
|
|
||||||
|
let entrypoint = elmi::ModuleNameCanonical {
|
||||||
|
package: elmi::PackageName::new("author", "project"),
|
||||||
|
module: crate::elm::parse_module_name(&data)?,
|
||||||
|
};
|
||||||
|
|
||||||
|
// step 3 find all the filepaths in the elm-stuff/0.19.1/* folder
|
||||||
|
let interfaces = elm::load_interfaces(&elm_cache_dir)?;
|
||||||
|
|
||||||
|
// Step 5, check for the desired function
|
||||||
|
let span = info_span!("resolved target function");
|
||||||
|
let timing_guard = span.enter();
|
||||||
|
|
||||||
|
let mut targets = Vec::new();
|
||||||
|
|
||||||
|
match interfaces.get(&entrypoint) {
|
||||||
|
Some(interface) => {
|
||||||
|
// todo search over the interface.values for something that has the type of derive
|
||||||
|
// macro
|
||||||
|
for (_key, annotation) in interface.values.iter() {
|
||||||
|
let elmi::CannonicalAnnotation(free_vars, tipe) = annotation;
|
||||||
|
match tipe {
|
||||||
|
elmi::Type::TType(module_name, name, args)
|
||||||
|
if module_name == "author/project/LiveTable.Derive"
|
||||||
|
&& name == "DeriveEditor" =>
|
||||||
|
{
|
||||||
|
if args.len() != 1 {
|
||||||
|
// We probably have a version mismatch of the tool and library. But I
|
||||||
|
// don't have any way of telling right now.
|
||||||
|
panic!(
|
||||||
|
"todo I don't understand how to parse the LiveTable Derive library"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
targets.push(resolve_table_argument(&args[0])?);
|
||||||
|
if !free_vars.is_empty() {
|
||||||
|
// We can't have free vars because that means we can't derive the serialize and
|
||||||
|
// deserialize functions without concreate types. The table editor component is
|
||||||
|
// not generic.
|
||||||
|
//panic!("todo we can't have free vars in livetable derive macro");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if targets.is_empty() {
|
||||||
|
return Err(CompilerError::MissingLiveTableDeriveMacroTarget(
|
||||||
|
file.clone(),
|
||||||
|
entrypoint.clone(),
|
||||||
|
)
|
||||||
|
.into());
|
||||||
|
};
|
||||||
|
//match interface.values.get(&entrypoint.1) {
|
||||||
|
//Some(annotation) => {
|
||||||
|
// let elmi::CannonicalAnnotation(_free_vars, tipe) = annotation;
|
||||||
|
|
||||||
|
// if is_astrid_pages_route(tipe) {
|
||||||
|
// ExecutionMode::AstridPagesRoute
|
||||||
|
// } else {
|
||||||
|
// let (input_type, output_type) = scripting::resolve_function_type(tipe)?;
|
||||||
|
// ExecutionMode::Scripting(input_type, output_type)
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//None => return Err(CompilerError::BadImport(entrypoint).into()),
|
||||||
|
}
|
||||||
|
None => return Err(CompilerError::MissingModuleTypeInformation(entrypoint).into()),
|
||||||
|
}
|
||||||
|
drop(timing_guard);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_table_argument(tipe: &elmi::Type) -> Result<i32, TypeError> {
|
||||||
|
let mut columns = Vec::new();
|
||||||
|
match tipe {
|
||||||
|
// The `fields` field of TAlias is empty if it aliasing a record.
|
||||||
|
elmi::Type::TAlias(_module_name, _type_name, _fields, ref alias) => match &**alias {
|
||||||
|
elmi::AliasType::Filled(elmi::Type::TRecord(fields, _name)) => {
|
||||||
|
//eprintln!("has field {} with type {:?}", field_name, field_type.tipe);
|
||||||
|
eprintln!("todo resolve this type");
|
||||||
|
// It seems the source_order is always 0. Not sure if there is a bug in my
|
||||||
|
// deserializing code or if Evan stopped saving this value but kept the file
|
||||||
|
// format.
|
||||||
|
for (field_name, field_type) in fields.iter() {
|
||||||
|
// check that column is acceptable
|
||||||
|
match &*field_type.tipe {
|
||||||
|
elmi::Type::TType(module_name, name, _args) => {
|
||||||
|
if module_name == "elm/core/Basics" && name == "Bool" {
|
||||||
|
columns.push(ColumnDefinition {
|
||||||
|
name: field_name.to_string(),
|
||||||
|
tipe: ColumnType::Bool,
|
||||||
|
sync_protocol_identifier: field_name.to_string(),
|
||||||
|
});
|
||||||
|
} else if module_name == "elm/core/Basics" && name == "Int" {
|
||||||
|
columns.push(ColumnDefinition {
|
||||||
|
name: field_name.to_string(),
|
||||||
|
tipe: ColumnType::BigInteger,
|
||||||
|
sync_protocol_identifier: field_name.to_string(),
|
||||||
|
});
|
||||||
|
} else if module_name == "elm/core/String" && name == "String" {
|
||||||
|
columns.push(ColumnDefinition {
|
||||||
|
name: field_name.to_string(),
|
||||||
|
tipe: ColumnType::String,
|
||||||
|
sync_protocol_identifier: field_name.to_string(),
|
||||||
|
});
|
||||||
|
} else if module_name == "author/project/LiveTable.Types"
|
||||||
|
&& name == "Email"
|
||||||
|
{
|
||||||
|
columns.push(ColumnDefinition {
|
||||||
|
name: field_name.to_string(),
|
||||||
|
tipe: ColumnType::Email,
|
||||||
|
sync_protocol_identifier: field_name.to_string(),
|
||||||
|
});
|
||||||
|
} else if module_name == "elm/bytes/Bytes" && name == "Bytes" {
|
||||||
|
} else if module_name == "author/project/LiveTable.Types"
|
||||||
|
&& name == "Attachment"
|
||||||
|
{
|
||||||
|
} else {
|
||||||
|
eprintln!("don't support field type yet {:?}\n\n", field_type.tipe);
|
||||||
|
//return Err(TypeError::OutputTypeNotSupported(tipe.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
eprintln!("don't support type yet {:?}\n\n", field_type.tipe);
|
||||||
|
//return Err(TypeError::CantEvalType(tipe.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(3)
|
||||||
|
}
|
||||||
|
elmi::AliasType::Filled(_tipe) => {
|
||||||
|
// TODO correct error type
|
||||||
|
Err(TypeError::CantEvalHoleyAlias)
|
||||||
|
}
|
||||||
|
elmi::AliasType::Holey(_) => Err(TypeError::CantEvalHoleyAlias),
|
||||||
|
},
|
||||||
|
_ => Err(TypeError::OutputTypeNotSupported(tipe.clone())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//ColumnType::MaybeBool => Maybe Bool,
|
||||||
|
//ColumnType::MaybeBigInteger => Maybe Int,
|
||||||
|
//ColumnType::MaybeString => Maybe String,
|
||||||
|
//ColumnType::Email => String,
|
||||||
|
//ColumnType::MaybeEmail => Maybe String,
|
||||||
|
//ColumnType::Url => String,
|
||||||
|
//ColumnType::MaybeUrl => Maybe String,
|
||||||
|
//ColumnType::Float => Float,
|
||||||
|
//ColumnType::MaybeFloat => Maybe Float,
|
||||||
|
//ColumnType::Double => Float,
|
||||||
|
//ColumnType::MaybeDouble => Maybe Float,
|
||||||
|
//ColumnType::Timestamp => #(posix_type.clone()),
|
||||||
|
//ColumnType::MaybeTimestamp => Maybe #(posix_type.clone()),
|
||||||
|
//ColumnType::ExactlyOneAttachment => LiveTable.Attachment,
|
||||||
|
//ColumnType::MaybeAttachment => Maybe LiveTable.Attachment,
|
||||||
|
//ColumnType::ListAttachment => List LiveTable.Attachment,
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::exec::astrid_pages::OutputType;
|
use crate::exec::astrid_pages::OutputType;
|
||||||
use genco_extra::elm::Tokens;
|
|
||||||
use genco::tokens::quoted;
|
use genco::tokens::quoted;
|
||||||
|
use genco_extra::elm::Tokens;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
// I manually made this derived deserialize implementation match the elm json encoder output. The
|
// I manually made this derived deserialize implementation match the elm json encoder output. The
|
||||||
|
|
|
||||||
|
|
@ -205,26 +205,26 @@ mod runtime {
|
||||||
let options = WorkerOptions {
|
let options = WorkerOptions {
|
||||||
bootstrap: BootstrapOptions {
|
bootstrap: BootstrapOptions {
|
||||||
args: vec![],
|
args: vec![],
|
||||||
apply_source_maps: false,
|
|
||||||
cpu_count: 1,
|
cpu_count: 1,
|
||||||
debug_flag: false,
|
debug_flag: false,
|
||||||
enable_testing_features: false,
|
enable_testing_features: false,
|
||||||
is_tty: false,
|
|
||||||
location: None,
|
location: None,
|
||||||
no_color: false,
|
no_color: false,
|
||||||
|
is_tty: false,
|
||||||
runtime_version: "0.50.0".to_string(),
|
runtime_version: "0.50.0".to_string(),
|
||||||
ts_version: "2.0.0".to_string(),
|
ts_version: "2.0.0".to_string(),
|
||||||
unstable: false,
|
unstable: false,
|
||||||
|
user_agent: "starmelon".to_string(),
|
||||||
},
|
},
|
||||||
extensions: extensions,
|
extensions: extensions,
|
||||||
unsafely_ignore_certificate_errors: None,
|
unsafely_ignore_certificate_errors: None,
|
||||||
root_cert_store: None,
|
root_cert_store: None,
|
||||||
user_agent: "hello_runtime".to_string(),
|
|
||||||
seed: None,
|
seed: None,
|
||||||
module_loader,
|
module_loader,
|
||||||
create_web_worker_cb,
|
create_web_worker_cb,
|
||||||
web_worker_preload_module_cb,
|
web_worker_preload_module_cb,
|
||||||
js_error_create_fn: None,
|
format_js_error_fn: None,
|
||||||
|
source_map_getter: None,
|
||||||
maybe_inspector_server: None,
|
maybe_inspector_server: None,
|
||||||
should_break_on_first_statement: false,
|
should_break_on_first_statement: false,
|
||||||
get_error_class_fn: Some(&get_error_class_name),
|
get_error_class_fn: Some(&get_error_class_name),
|
||||||
|
|
@ -233,6 +233,7 @@ mod runtime {
|
||||||
broadcast_channel: InMemoryBroadcastChannel::default(),
|
broadcast_channel: InMemoryBroadcastChannel::default(),
|
||||||
shared_array_buffer_store: None,
|
shared_array_buffer_store: None,
|
||||||
compiled_wasm_module_store: None,
|
compiled_wasm_module_store: None,
|
||||||
|
stdio: deno_runtime::ops::io::Stdio::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let main_module = deno_core::resolve_path(path_str)?;
|
let main_module = deno_core::resolve_path(path_str)?;
|
||||||
|
|
@ -311,7 +312,7 @@ mod runtime {
|
||||||
//let code = if let Some((ref source, _)) = is_data_uri {
|
//let code = if let Some((ref source, _)) = is_data_uri {
|
||||||
// source.to_string()
|
// source.to_string()
|
||||||
//} else {
|
//} else {
|
||||||
let code = self.0.to_string();
|
let code: Box<[u8]> = self.0.as_bytes().into();
|
||||||
//};
|
//};
|
||||||
async move {
|
async move {
|
||||||
//if is_data_uri.is_none() && module_specifier.to_string() != SPECIFIER {
|
//if is_data_uri.is_none() && module_specifier.to_string() != SPECIFIER {
|
||||||
|
|
|
||||||
36
src/reactor/ui/Router.elm
Normal file
36
src/reactor/ui/Router.elm
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
module Router exposing (fmain, Table)
|
||||||
|
|
||||||
|
import Html exposing (Html, text, div)
|
||||||
|
import Time exposing (Posix)
|
||||||
|
import Foo
|
||||||
|
|
||||||
|
fmain =
|
||||||
|
text "Hello world"
|
||||||
|
|
||||||
|
type alias Table =
|
||||||
|
{ target: String
|
||||||
|
, path: String
|
||||||
|
, start : Posix
|
||||||
|
, end : Posix
|
||||||
|
, status : Status
|
||||||
|
}
|
||||||
|
|
||||||
|
type Status
|
||||||
|
= Published
|
||||||
|
| Draft
|
||||||
|
|
||||||
|
|
||||||
|
-- You could write the type out for this, but it does not matter.
|
||||||
|
--deriveTableEditor =
|
||||||
|
-- DeriveTableEditor
|
||||||
|
-- { containerAttributes =
|
||||||
|
-- [ Livetable.Attributes.rename "foobar"
|
||||||
|
-- ]
|
||||||
|
-- , fieldAttributes =
|
||||||
|
-- { target = [ columnName "Page" ]
|
||||||
|
-- , path = [ columnName "Target"]
|
||||||
|
-- , start = [ columnName "Start" ]
|
||||||
|
-- , end = [ columnName "End" ]
|
||||||
|
-- , status = [ columnName "Status" ]
|
||||||
|
-- }
|
||||||
|
-- }
|
||||||
|
|
@ -256,7 +256,8 @@ impl CompilerError {
|
||||||
vcat([to_message_bar(title, ""), Doc::text(""), message])
|
vcat([to_message_bar(title, ""), Doc::text(""), message])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Here is an example of an error message
|
||||||
|
// ```
|
||||||
// -- MODULE NAME MISMATCH ------------------------------ src/reactor/ui/Router.elm
|
// -- MODULE NAME MISMATCH ------------------------------ src/reactor/ui/Router.elm
|
||||||
//
|
//
|
||||||
// It looks like this module name is out of sync:
|
// It looks like this module name is out of sync:
|
||||||
|
|
@ -272,6 +273,7 @@ impl CompilerError {
|
||||||
// easier to explore unfamiliar codebases! So if you want to keep the current
|
// easier to explore unfamiliar codebases! So if you want to keep the current
|
||||||
// module name, try renaming the file instead.
|
// module name, try renaming the file instead.
|
||||||
//
|
//
|
||||||
|
// ```
|
||||||
|
|
||||||
impl InterpreterError {
|
impl InterpreterError {
|
||||||
pub fn to_doc(&self) -> Doc {
|
pub fn to_doc(&self) -> Doc {
|
||||||
|
|
|
||||||
531
src/transpile.rs
531
src/transpile.rs
|
|
@ -137,105 +137,75 @@ pub fn transpile(
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(node) = objects.get(&entrypoint) {
|
if let Some(node) = objects.get(&entrypoint) {
|
||||||
match node {
|
|
||||||
elmi::Node::Define(elmi::Expr::Function(ref parameters, ref body), deps) => {
|
|
||||||
for dep in deps {
|
|
||||||
println!("I depend on {}", dep);
|
|
||||||
}
|
|
||||||
let elmi::CannonicalAnnotation(elmi::FreeVars(free_variables), tipe) = signature;
|
|
||||||
|
|
||||||
// So I want a map of symbol to is function with arity or is value. I don't need a
|
|
||||||
// scope mechansim because elm prevents variable shadowing. So the map can
|
|
||||||
// overwrite values for sibling scopes. So everytime I visit an Expr I want to
|
|
||||||
// return the arity of that expression. One problem is I need to generate the
|
|
||||||
// arguments before serializing the body of the closure
|
|
||||||
|
|
||||||
let (parameter_types, return_type) =
|
|
||||||
extract_function_types(&tipe, parameters.len()).unwrap();
|
|
||||||
|
|
||||||
let xs = parameters
|
|
||||||
.into_iter()
|
|
||||||
.zip(parameter_types.into_iter())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
// TODO add any TLambdas in the signature to the type parameters of the functions
|
|
||||||
// as where bounds
|
|
||||||
|
|
||||||
let mut tokens = rust::Tokens::new();
|
let mut tokens = rust::Tokens::new();
|
||||||
codegen_function(
|
lua_codegen::codegen(
|
||||||
&mut tokens,
|
&mut tokens,
|
||||||
|
&interfaces,
|
||||||
&mut symbol_table,
|
&mut symbol_table,
|
||||||
&entrypoint.1,
|
&entrypoint,
|
||||||
&free_variables,
|
node,
|
||||||
&xs,
|
|
||||||
return_type,
|
|
||||||
body,
|
|
||||||
);
|
);
|
||||||
println!("{}", tokens.to_file_string().unwrap());
|
|
||||||
}
|
}
|
||||||
_ => println!("I don't know how to transpile that node"),
|
//println!("total symbols {}", objects.len());
|
||||||
}
|
|
||||||
}
|
|
||||||
println!("total symbols {}", objects.len());
|
|
||||||
//let visited: HashSet<Global> = HashSet::new();
|
//let visited: HashSet<Global> = HashSet::new();
|
||||||
for (_key, node) in objects.iter() {
|
//for (_key, node) in objects.iter() {
|
||||||
//println!("key {}", key);
|
// //println!("key {}", key);
|
||||||
match node {
|
// match node {
|
||||||
elmi::Node::Define(_expr, deps) => {
|
// elmi::Node::Define(_expr, deps) => {
|
||||||
//println!("key => {:?}", expr);
|
// //println!("key => {:?}", expr);
|
||||||
for dep in deps.iter() {
|
// for dep in deps.iter() {
|
||||||
if !objects.contains_key(&dep) {
|
// if !objects.contains_key(&dep) {
|
||||||
println!("could not find dep {}", dep);
|
// println!("could not find dep {}", dep);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
elmi::Node::DefineTailFunc(_, _, deps) => {
|
// elmi::Node::DefineTailFunc(_, _, deps) => {
|
||||||
for dep in deps.iter() {
|
// for dep in deps.iter() {
|
||||||
if !objects.contains_key(&dep) {
|
// if !objects.contains_key(&dep) {
|
||||||
println!("could not find dep {}", dep);
|
// println!("could not find dep {}", dep);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
elmi::Node::Ctor(_, _) => {}
|
// elmi::Node::Ctor(_, _) => {}
|
||||||
elmi::Node::Enum(_) => {}
|
// elmi::Node::Enum(_) => {}
|
||||||
elmi::Node::Box => {}
|
// elmi::Node::Box => {}
|
||||||
elmi::Node::Link(dep) => {
|
// elmi::Node::Link(dep) => {
|
||||||
if !objects.contains_key(&dep) {
|
// if !objects.contains_key(&dep) {
|
||||||
println!("could not find dep {}", dep);
|
// println!("could not find dep {}", dep);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
elmi::Node::Cycle(_, _, _, deps) => {
|
// elmi::Node::Cycle(_, _, _, deps) => {
|
||||||
for dep in deps.iter() {
|
// for dep in deps.iter() {
|
||||||
if !objects.contains_key(&dep) {
|
// if !objects.contains_key(&dep) {
|
||||||
println!("could not find dep {}", dep);
|
// println!("could not find dep {}", dep);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
elmi::Node::Manager(_) => (),
|
// elmi::Node::Manager(_) => (),
|
||||||
elmi::Node::Kernel(_, deps) => {
|
// elmi::Node::Kernel(_, deps) => {
|
||||||
for dep in deps.iter() {
|
// for dep in deps.iter() {
|
||||||
if !objects.contains_key(&dep) {
|
// if !objects.contains_key(&dep) {
|
||||||
println!("could not find dep {}", dep);
|
// println!("could not find dep {}", dep);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
elmi::Node::PortIncoming(_, deps) => {
|
// elmi::Node::PortIncoming(_, deps) => {
|
||||||
for dep in deps.iter() {
|
// for dep in deps.iter() {
|
||||||
if !objects.contains_key(&dep) {
|
// if !objects.contains_key(&dep) {
|
||||||
println!("could not find dep {}", dep);
|
// println!("could not find dep {}", dep);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
elmi::Node::PortOutgoing(_, deps) => {
|
// elmi::Node::PortOutgoing(_, deps) => {
|
||||||
for dep in deps.iter() {
|
// for dep in deps.iter() {
|
||||||
if !objects.contains_key(&dep) {
|
// if !objects.contains_key(&dep) {
|
||||||
println!("could not find dep {}", dep);
|
// println!("could not find dep {}", dep);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
// step 6, start generating rust code using a tree visitor on each of the entry points.
|
// step 6, start generating rust code using a tree visitor on each of the entry points.
|
||||||
// Accumulate the contents of each rust module in map.
|
// Accumulate the contents of each rust module in map.
|
||||||
|
|
@ -256,12 +226,12 @@ pub fn transpile(
|
||||||
type SymbolTable<'a> = HashMap<Symbol<'a>, SymbolKind<'a>>;
|
type SymbolTable<'a> = HashMap<Symbol<'a>, SymbolKind<'a>>;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
enum Symbol<'a> {
|
pub(crate) enum Symbol<'a> {
|
||||||
Global(&'a elmi::Global),
|
Global(&'a elmi::Global),
|
||||||
Local(&'a elmi::Name),
|
Local(&'a elmi::Name),
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SymbolKind<'a> {
|
pub(crate) enum SymbolKind<'a> {
|
||||||
Function { arity: usize, tipe: &'a elmi::Type },
|
Function { arity: usize, tipe: &'a elmi::Type },
|
||||||
Value { tipe: &'a elmi::Type },
|
Value { tipe: &'a elmi::Type },
|
||||||
}
|
}
|
||||||
|
|
@ -362,7 +332,67 @@ fn validate_output_type(tipe: &elmi::Type) -> Result<(), TypeError> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn codegen_function(
|
mod rust_codegen {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub(crate) fn codegen(
|
||||||
|
tokens: &mut rust::Tokens,
|
||||||
|
interfaces: &HashMap<elmi::ModuleNameCanonical, elmi::Interface>,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
symbol: &elmi::Global,
|
||||||
|
node: &elmi::Node,
|
||||||
|
) {
|
||||||
|
match node {
|
||||||
|
elmi::Node::Define(elmi::Expr::Function(ref parameters, ref body), deps) => {
|
||||||
|
for dep in deps {
|
||||||
|
println!("I depend on {}", dep);
|
||||||
|
}
|
||||||
|
let signature = match interfaces.get(&symbol.0) {
|
||||||
|
Some(interface) => match interface.values.get(&symbol.1) {
|
||||||
|
Some(annotation) => {
|
||||||
|
let elmi::CannonicalAnnotation(_free_vars, ref tipe) = annotation;
|
||||||
|
|
||||||
|
annotation
|
||||||
|
}
|
||||||
|
None => return,
|
||||||
|
},
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
let elmi::CannonicalAnnotation(elmi::FreeVars(free_variables), tipe) = signature;
|
||||||
|
|
||||||
|
// So I want a map of symbol to is function with arity or is value. I don't need a
|
||||||
|
// scope mechansim because elm prevents variable shadowing. So the map can
|
||||||
|
// overwrite values for sibling scopes. So everytime I visit an Expr I want to
|
||||||
|
// return the arity of that expression. One problem is I need to generate the
|
||||||
|
// arguments before serializing the body of the closure
|
||||||
|
|
||||||
|
let (parameter_types, return_type) =
|
||||||
|
extract_function_types(&tipe, parameters.len()).unwrap();
|
||||||
|
|
||||||
|
let xs = parameters
|
||||||
|
.into_iter()
|
||||||
|
.zip(parameter_types.into_iter())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// TODO add any TLambdas in the signature to the type parameters of the functions
|
||||||
|
// as where bounds
|
||||||
|
|
||||||
|
codegen_function(
|
||||||
|
tokens,
|
||||||
|
symbol_table,
|
||||||
|
&symbol.1,
|
||||||
|
&free_variables,
|
||||||
|
&xs,
|
||||||
|
return_type,
|
||||||
|
body,
|
||||||
|
);
|
||||||
|
println!("{}", tokens.to_file_string().unwrap());
|
||||||
|
}
|
||||||
|
_ => println!("I don't know how to transpile that node"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn codegen_function(
|
||||||
tokens: &mut rust::Tokens,
|
tokens: &mut rust::Tokens,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
name: &elmi::Name,
|
name: &elmi::Name,
|
||||||
|
|
@ -370,7 +400,7 @@ fn codegen_function(
|
||||||
parameters: &[(&elmi::Name, elmi::Type)],
|
parameters: &[(&elmi::Name, elmi::Type)],
|
||||||
return_type: elmi::Type,
|
return_type: elmi::Type,
|
||||||
body: &elmi::Expr,
|
body: &elmi::Expr,
|
||||||
) {
|
) {
|
||||||
quote_in! { *tokens =>
|
quote_in! { *tokens =>
|
||||||
fn #name#(if !type_variables.is_empty() =>
|
fn #name#(if !type_variables.is_empty() =>
|
||||||
<#(for tvar in type_variables.iter() join (, ) =>
|
<#(for tvar in type_variables.iter() join (, ) =>
|
||||||
|
|
@ -382,9 +412,9 @@ fn codegen_function(
|
||||||
#(ref out { codegen_expr(out, symbol_table, body) })
|
#(ref out { codegen_expr(out, symbol_table, body) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn codegen_type(tokens: &mut rust::Tokens, tipe: &elmi::Type) {
|
fn codegen_type(tokens: &mut rust::Tokens, tipe: &elmi::Type) {
|
||||||
quote_in! { *tokens =>
|
quote_in! { *tokens =>
|
||||||
#(match tipe {
|
#(match tipe {
|
||||||
elmi::Type::TLambda(a, b) => {
|
elmi::Type::TLambda(a, b) => {
|
||||||
|
|
@ -441,19 +471,19 @@ fn codegen_type(tokens: &mut rust::Tokens, tipe: &elmi::Type) {
|
||||||
//}
|
//}
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn codegen_name_from_global(
|
fn codegen_name_from_global(
|
||||||
tokens: &mut rust::Tokens,
|
tokens: &mut rust::Tokens,
|
||||||
home: &elmi::ModuleNameCanonical,
|
home: &elmi::ModuleNameCanonical,
|
||||||
name: &elmi::Name,
|
name: &elmi::Name,
|
||||||
) {
|
) {
|
||||||
quote_in! { *tokens =>
|
quote_in! { *tokens =>
|
||||||
#(ref out => codegen_home_to_builder(out, home) )__#name
|
#(ref out => codegen_home_to_builder(out, home) )__#name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn codegen_home_to_builder(tokens: &mut rust::Tokens, global: &elmi::ModuleNameCanonical) {
|
fn codegen_home_to_builder(tokens: &mut rust::Tokens, global: &elmi::ModuleNameCanonical) {
|
||||||
let elmi::ModuleNameCanonical {
|
let elmi::ModuleNameCanonical {
|
||||||
package: elmi::PackageName { author, project },
|
package: elmi::PackageName { author, project },
|
||||||
module: home,
|
module: home,
|
||||||
|
|
@ -462,9 +492,9 @@ fn codegen_home_to_builder(tokens: &mut rust::Tokens, global: &elmi::ModuleNameC
|
||||||
quote_in! { *tokens =>
|
quote_in! { *tokens =>
|
||||||
_#(author.replace("-", "_"))_#(project.replace("-", "_"))__#(home.0.replace(".", "_"))
|
_#(author.replace("-", "_"))_#(project.replace("-", "_"))__#(home.0.replace(".", "_"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn codegen_expr(tokens: &mut rust::Tokens, symbol_table: &mut SymbolTable, expr: &elmi::Expr) {
|
fn codegen_expr(tokens: &mut rust::Tokens, symbol_table: &mut SymbolTable, expr: &elmi::Expr) {
|
||||||
match expr {
|
match expr {
|
||||||
elmi::Expr::Bool(true) => quote_in! { *tokens => true },
|
elmi::Expr::Bool(true) => quote_in! { *tokens => true },
|
||||||
elmi::Expr::Bool(false) => quote_in! { *tokens => false },
|
elmi::Expr::Bool(false) => quote_in! { *tokens => false },
|
||||||
|
|
@ -513,10 +543,280 @@ fn codegen_expr(tokens: &mut rust::Tokens, symbol_table: &mut SymbolTable, expr:
|
||||||
if args.len() < *arity {
|
if args.len() < *arity {
|
||||||
let mut closure_args = Vec::new();
|
let mut closure_args = Vec::new();
|
||||||
for i in 0..(*arity - args.len()) {
|
for i in 0..(*arity - args.len()) {
|
||||||
closure_args.push(elmi::Expr::VarLocal(elmi::Name(format!(
|
closure_args.push(elmi::Expr::VarLocal(elmi::Name(
|
||||||
"_partial{}",
|
format!("_partial{}", i),
|
||||||
i
|
)));
|
||||||
))));
|
}
|
||||||
|
quote_in! { *tokens =>
|
||||||
|
Box::new(| #(for arg in closure_args.iter() join (, ) => #(ref out => codegen_expr(out, symbol_table, arg))) | {
|
||||||
|
#(ref out => {
|
||||||
|
codegen_name_from_global(out, home, name)
|
||||||
|
})(
|
||||||
|
#(for arg in args.iter().chain(closure_args.iter()) join (,#<push>) => #(ref out =>
|
||||||
|
codegen_expr(out, symbol_table, arg) )
|
||||||
|
)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote_in! { *tokens =>
|
||||||
|
#(ref out => {
|
||||||
|
codegen_name_from_global(out, home, name)
|
||||||
|
})(
|
||||||
|
#(for arg in args join (,#<push>) => #(ref out =>
|
||||||
|
codegen_expr(out, symbol_table, arg) )
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//println!("found the function symbol {}, arity {}", global, arity);
|
||||||
|
}
|
||||||
|
Some(SymbolKind::Value { tipe: _ }) => {
|
||||||
|
panic!("tried to call a symbol we thought was a value: {}", global);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
panic!("tried to call a symbol we don't know about: {}", global);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elmi::Expr::VarLocal(name) => {
|
||||||
|
quote_in! { *tokens =>
|
||||||
|
#name(
|
||||||
|
#(for arg in args join (,#<push>) => #(ref out =>
|
||||||
|
codegen_expr(out, symbol_table, arg) )
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
println!("I was unable to call an expression");
|
||||||
|
// TODO write a function that can take an expression and return the arity using
|
||||||
|
// the symbol table from the bottom up.
|
||||||
|
quote_in! { *tokens =>
|
||||||
|
#(format!("{:?}", fexpr))
|
||||||
|
}
|
||||||
|
//panic!("calling an expression not yet supported");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
//elmi::Expr::TailCall(Name, Vec<(Name, Expr)>),
|
||||||
|
elmi::Expr::If(branches, _final_branch) => {
|
||||||
|
quote_in! { *tokens =>
|
||||||
|
#(for (condition, expr) in branches join (#<push>#("} else")) =>
|
||||||
|
if #(ref out => codegen_expr(out, symbol_table, condition)) #("{")
|
||||||
|
#(ref out => codegen_expr(out, symbol_table, expr))
|
||||||
|
) #("} else {")
|
||||||
|
#(ref out => codegen_expr(out, symbol_table, expr))
|
||||||
|
#("}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elmi::Expr::Let(def, expr) => {
|
||||||
|
quote_in! { *tokens =>
|
||||||
|
#(ref out => codegen_def(out, symbol_table, def))
|
||||||
|
#<push>
|
||||||
|
#(ref out => codegen_expr(out, symbol_table, expr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//elmi::Expr::Destruct(Destructor, Box<Expr>),
|
||||||
|
//elmi::Expr::Case(Name, Name, Decider<Choice>, Vec<(i64, Expr)>) => {
|
||||||
|
elmi::Expr::Case(label, root, decider, jumps) => {
|
||||||
|
println!("jumps {:?}", jumps);
|
||||||
|
}
|
||||||
|
elmi::Expr::Accessor(name) => {
|
||||||
|
quote_in! { *tokens =>
|
||||||
|
Box::new(|_v| { _v.#name })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//elmi::Expr::Access(Box<Expr>, Name),
|
||||||
|
//elmi::Expr::Update(Box<Expr>, HashMap<Name, Expr>),
|
||||||
|
//elmi::Expr::Record(HashMap<Name, Expr>),
|
||||||
|
elmi::Expr::Unit => (),
|
||||||
|
elmi::Expr::Tuple(a, b, None) => {
|
||||||
|
quote_in! { *tokens =>
|
||||||
|
( #(ref out => codegen_expr(out, symbol_table, a) ), #(ref out => codegen_expr(out, symbol_table, b) ) )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elmi::Expr::Tuple(a, b, Some(c)) => {
|
||||||
|
quote_in! { *tokens =>
|
||||||
|
( #(ref out => codegen_expr(out, symbol_table, a) ), #(ref out => codegen_expr(out, symbol_table, b) ), #(ref out => codegen_expr(out, symbol_table, c) ) )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//elmi::Expr::Shader(ShaderSource, HashSet<Name>, HashSet<Name>),
|
||||||
|
_ => quote_in! { *tokens => #(format!("{:?}", expr)) },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn codegen_def(tokens: &mut rust::Tokens, symbol_table: &mut SymbolTable, def: &elmi::Def) {
|
||||||
|
match def {
|
||||||
|
elmi::Def::Def(name, expr) => {
|
||||||
|
quote_in! { *tokens =>
|
||||||
|
let #name = #(ref out => codegen_expr(out, symbol_table, expr) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elmi::Def::TailDef(name, arg_names, expr) => {
|
||||||
|
quote_in! { *tokens =>
|
||||||
|
|#(for arg in arg_names join (, ) => mut #arg) | {
|
||||||
|
#("'")#name : loop {
|
||||||
|
#(ref out => codegen_expr(out, symbol_table, expr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod lua_codegen {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub(crate) fn codegen(
|
||||||
|
tokens: &mut rust::Tokens,
|
||||||
|
interfaces: &HashMap<elmi::ModuleNameCanonical, elmi::Interface>,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
symbol: &elmi::Global,
|
||||||
|
node: &elmi::Node,
|
||||||
|
) {
|
||||||
|
match node {
|
||||||
|
elmi::Node::Define(elmi::Expr::Function(ref parameters, ref body), deps) => {
|
||||||
|
for dep in deps {
|
||||||
|
println!("I depend on {}", dep);
|
||||||
|
}
|
||||||
|
let signature = match interfaces.get(&symbol.0) {
|
||||||
|
Some(interface) => match interface.values.get(&symbol.1) {
|
||||||
|
Some(annotation) => {
|
||||||
|
let elmi::CannonicalAnnotation(_free_vars, ref tipe) = annotation;
|
||||||
|
|
||||||
|
annotation
|
||||||
|
}
|
||||||
|
None => return,
|
||||||
|
},
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
let elmi::CannonicalAnnotation(elmi::FreeVars(free_variables), tipe) = signature;
|
||||||
|
|
||||||
|
// So I want a map of symbol to is function with arity or is value. I don't need a
|
||||||
|
// scope mechansim because elm prevents variable shadowing. So the map can
|
||||||
|
// overwrite values for sibling scopes. So everytime I visit an Expr I want to
|
||||||
|
// return the arity of that expression. One problem is I need to generate the
|
||||||
|
// arguments before serializing the body of the closure
|
||||||
|
|
||||||
|
let (parameter_types, return_type) =
|
||||||
|
extract_function_types(&tipe, parameters.len()).unwrap();
|
||||||
|
|
||||||
|
let xs = parameters
|
||||||
|
.into_iter()
|
||||||
|
.zip(parameter_types.into_iter())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// TODO add any TLambdas in the signature to the type parameters of the functions
|
||||||
|
// as where bounds
|
||||||
|
|
||||||
|
codegen_function(
|
||||||
|
tokens,
|
||||||
|
symbol_table,
|
||||||
|
&symbol.1,
|
||||||
|
&free_variables,
|
||||||
|
&xs,
|
||||||
|
return_type,
|
||||||
|
body,
|
||||||
|
);
|
||||||
|
println!("{}", tokens.to_file_string().unwrap());
|
||||||
|
}
|
||||||
|
_ => println!("I don't know how to transpile that node"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn codegen_function(
|
||||||
|
tokens: &mut rust::Tokens,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
name: &elmi::Name,
|
||||||
|
type_variables: &HashSet<elmi::Name>,
|
||||||
|
parameters: &[(&elmi::Name, elmi::Type)],
|
||||||
|
return_type: elmi::Type,
|
||||||
|
body: &elmi::Expr,
|
||||||
|
) {
|
||||||
|
quote_in! { *tokens =>
|
||||||
|
function #name(#(for (parameter, _tipe) in parameters.iter() join (, ) =>
|
||||||
|
#parameter
|
||||||
|
))
|
||||||
|
#(ref out { codegen_expr(out, symbol_table, body) })
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn codegen_name_from_global(
|
||||||
|
tokens: &mut rust::Tokens,
|
||||||
|
home: &elmi::ModuleNameCanonical,
|
||||||
|
name: &elmi::Name,
|
||||||
|
) {
|
||||||
|
quote_in! { *tokens =>
|
||||||
|
#(ref out => codegen_home_to_builder(out, home) )__#name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn codegen_home_to_builder(tokens: &mut rust::Tokens, global: &elmi::ModuleNameCanonical) {
|
||||||
|
let elmi::ModuleNameCanonical {
|
||||||
|
package: elmi::PackageName { author, project },
|
||||||
|
module: home,
|
||||||
|
} = global;
|
||||||
|
|
||||||
|
quote_in! { *tokens =>
|
||||||
|
_#(author.replace("-", "_"))_#(project.replace("-", "_"))__#(home.0.replace(".", "_"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn codegen_expr(tokens: &mut rust::Tokens, symbol_table: &mut SymbolTable, expr: &elmi::Expr) {
|
||||||
|
match expr {
|
||||||
|
elmi::Expr::Bool(true) => quote_in! { *tokens => true },
|
||||||
|
elmi::Expr::Bool(false) => quote_in! { *tokens => false },
|
||||||
|
elmi::Expr::Chr(c) => quote_in! { *tokens => #(quoted(c)) },
|
||||||
|
elmi::Expr::Str(s) => quote_in! { *tokens => #(quoted(s)) },
|
||||||
|
elmi::Expr::Int(x) => quote_in! { *tokens => #(x.to_string()) },
|
||||||
|
elmi::Expr::Float(x) => quote_in! { *tokens => #(x.to_string()) },
|
||||||
|
elmi::Expr::VarLocal(name) => {
|
||||||
|
quote_in! { *tokens =>
|
||||||
|
#name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elmi::Expr::VarGlobal(elmi::Global(home, name)) => {
|
||||||
|
quote_in! { *tokens =>
|
||||||
|
#(ref out => codegen_name_from_global(out, home, name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//elmi::Expr::VarEnum(Global, IndexZeroBased),
|
||||||
|
//elmi::Expr::VarBox(Global),
|
||||||
|
//elmi::Expr::VarCycle(ModuleNameCanonical, Name),
|
||||||
|
//elmi::Expr::VarDebug(Name, ModuleNameCanonical, AnnotationRegion, Option<Name>),
|
||||||
|
//elmi::Expr::VarKernel(Name, Name),
|
||||||
|
elmi::Expr::List(xs) => {
|
||||||
|
if xs.is_empty() {
|
||||||
|
quote_in! { *tokens => &[] }
|
||||||
|
} else {
|
||||||
|
quote_in! { *tokens =>
|
||||||
|
&[
|
||||||
|
#(for x in xs join (,#<push>) => #(ref out => codegen_expr(out, symbol_table, x) ) )
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elmi::Expr::Function(_parameters, _body) => {
|
||||||
|
quote_in! { *tokens =>
|
||||||
|
"i don't know how to code gen a function expression"
|
||||||
|
//#(for elmi::Name(ref parameter) in parameters.iter() join (, ) =>
|
||||||
|
//)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elmi::Expr::Call(ref fexpr, args) => {
|
||||||
|
match &**fexpr {
|
||||||
|
elmi::Expr::VarGlobal(global @ elmi::Global(home, name)) => {
|
||||||
|
match symbol_table.get(&Symbol::Global(global)) {
|
||||||
|
Some(SymbolKind::Function { arity, tipe: _ }) => {
|
||||||
|
if args.len() < *arity {
|
||||||
|
let mut closure_args = Vec::new();
|
||||||
|
for i in 0..(*arity - args.len()) {
|
||||||
|
closure_args.push(elmi::Expr::VarLocal(elmi::Name(
|
||||||
|
format!("_partial{}", i),
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
quote_in! { *tokens =>
|
quote_in! { *tokens =>
|
||||||
Box::new(| #(for arg in closure_args.iter() join (, ) => #(ref out => codegen_expr(out, symbol_table, arg))) | {
|
Box::new(| #(for arg in closure_args.iter() join (, ) => #(ref out => codegen_expr(out, symbol_table, arg))) | {
|
||||||
|
|
@ -590,6 +890,10 @@ fn codegen_expr(tokens: &mut rust::Tokens, symbol_table: &mut SymbolTable, expr:
|
||||||
}
|
}
|
||||||
//elmi::Expr::Destruct(Destructor, Box<Expr>),
|
//elmi::Expr::Destruct(Destructor, Box<Expr>),
|
||||||
//elmi::Expr::Case(Name, Name, Decider<Choice>, Vec<(i64, Expr)>),
|
//elmi::Expr::Case(Name, Name, Decider<Choice>, Vec<(i64, Expr)>),
|
||||||
|
elmi::Expr::Case(label, root, decider, jumps) => {
|
||||||
|
println!("decider {:#?}", decider);
|
||||||
|
println!("jumps {:?}", jumps);
|
||||||
|
}
|
||||||
elmi::Expr::Accessor(name) => {
|
elmi::Expr::Accessor(name) => {
|
||||||
quote_in! { *tokens =>
|
quote_in! { *tokens =>
|
||||||
Box::new(|_v| { _v.#name })
|
Box::new(|_v| { _v.#name })
|
||||||
|
|
@ -612,13 +916,13 @@ fn codegen_expr(tokens: &mut rust::Tokens, symbol_table: &mut SymbolTable, expr:
|
||||||
//elmi::Expr::Shader(ShaderSource, HashSet<Name>, HashSet<Name>),
|
//elmi::Expr::Shader(ShaderSource, HashSet<Name>, HashSet<Name>),
|
||||||
_ => quote_in! { *tokens => #(format!("{:?}", expr)) },
|
_ => quote_in! { *tokens => #(format!("{:?}", expr)) },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn codegen_def(tokens: &mut rust::Tokens, symbol_table: &mut SymbolTable, def: &elmi::Def) {
|
fn codegen_def(tokens: &mut rust::Tokens, symbol_table: &mut SymbolTable, def: &elmi::Def) {
|
||||||
match def {
|
match def {
|
||||||
elmi::Def::Def(name, expr) => {
|
elmi::Def::Def(name, expr) => {
|
||||||
quote_in! { *tokens =>
|
quote_in! { *tokens =>
|
||||||
let #name = #(ref out => codegen_expr(out, symbol_table, expr) );
|
local #name = #(ref out => codegen_expr(out, symbol_table, expr) )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elmi::Def::TailDef(name, arg_names, expr) => {
|
elmi::Def::TailDef(name, arg_names, expr) => {
|
||||||
|
|
@ -631,6 +935,7 @@ fn codegen_def(tokens: &mut rust::Tokens, symbol_table: &mut SymbolTable, def: &
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_function_types(
|
fn extract_function_types(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue