diff --git a/Cargo.lock b/Cargo.lock index 30e8d5658e..407b08b760 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "MacTypes-sys" version = "2.1.0" @@ -170,7 +172,7 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -304,7 +306,7 @@ dependencies = [ [[package]] name = "codespan" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -315,10 +317,10 @@ dependencies = [ [[package]] name = "codespan-reporting" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "codespan 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "codespan 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -783,8 +785,8 @@ name = "gluon" version = "0.11.2" dependencies = [ "bincode 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "codespan 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "codespan-reporting 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "codespan 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "codespan-reporting 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "collect-mac 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "compiletest_rs 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "criterion 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -833,8 +835,8 @@ version = "0.11.2" dependencies = [ "anymap 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "codespan 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "codespan-reporting 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "codespan 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "codespan-reporting 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "collect-mac 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -865,8 +867,8 @@ dependencies = [ name = "gluon_check" version = "0.11.2" dependencies = [ - "codespan 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "codespan-reporting 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "codespan 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "codespan-reporting 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "collect-mac 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -904,7 +906,7 @@ dependencies = [ name = "gluon_completion" version = "0.11.2" dependencies = [ - "codespan 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "codespan 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "collect-mac 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -945,7 +947,7 @@ dependencies = [ name = "gluon_format" version = "0.11.2" dependencies = [ - "codespan 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "codespan 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "gluon 0.11.2", @@ -960,8 +962,8 @@ dependencies = [ name = "gluon_parser" version = "0.11.2" dependencies = [ - "codespan 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "codespan-reporting 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "codespan 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "codespan-reporting 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "collect-mac 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -982,8 +984,8 @@ version = "0.11.2" dependencies = [ "app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "codespan 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "codespan-reporting 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "codespan 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "codespan-reporting 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1012,7 +1014,7 @@ name = "gluon_vm" version = "0.11.2" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "codespan 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "codespan 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "collect-mac 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "frunk_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1027,6 +1029,7 @@ dependencies = [ "lalrpop-util 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mopa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "pretty 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2222,7 +2225,7 @@ name = "sha2" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2991,7 +2994,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" -"checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" +"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" "checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" @@ -3007,8 +3010,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum codespan 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "004def512a9848b23a68ed110927d102b0e6d9f3dc732e28570879afde051f8c" -"checksum codespan-reporting 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b329932b380f719f861e2844dcafea53e31821a53b76a1218364d3433cb472" +"checksum codespan 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03ed0fdf823b4a01c3b6a3e086b4d0a2def8d3cb75b110ec5c988fe2790860a9" +"checksum codespan-reporting 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2ae73f6c4b3803dc2a0fe08ed1ce40e8f3f94ecc8394a82e0696bbc86d4e4fc3" "checksum collect-mac 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f168712e49987bd2f51cb855c4585999e12b1a0abdff60fea4b81b41f2010264" "checksum compiletest_rs 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0d76d4322a40f6b0db7259d4f2c8a65ed8b0d84fce0bbc61b98cf47f8ec6eec3" "checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980" diff --git a/Cargo.toml b/Cargo.toml index 1122af15f7..8437c190d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,8 +35,8 @@ collect-mac = "0.1.0" either = "1.0.0" itertools = "0.8" futures = "0.1.11" -codespan = "0.2" -codespan-reporting = "0.2" +codespan = "0.3" +codespan-reporting = "0.3" serde = { version = "1.0.0", optional = true } serde_state = { version = "0.4.0", optional = true } diff --git a/base/Cargo.toml b/base/Cargo.toml index 818f60a0e1..c4f74e2f8f 100644 --- a/base/Cargo.toml +++ b/base/Cargo.toml @@ -22,8 +22,8 @@ collect-mac = "0.1.0" anymap = "0.12.0" itertools = "0.8" ordered-float = "1" -codespan = "0.2" -codespan-reporting = "0.2" +codespan = "0.3" +codespan-reporting = "0.3" either = "1" stable_deref_trait = "1" vec_map = "0.8" diff --git a/check/Cargo.toml b/check/Cargo.toml index b0870d02cb..1cfefd099a 100644 --- a/check/Cargo.toml +++ b/check/Cargo.toml @@ -22,8 +22,8 @@ rpds = "0.5" stable_deref_trait = "1" quick-error = "1" -codespan = "0.2" -codespan-reporting = "0.2" +codespan = "0.3" +codespan-reporting = "0.3" strsim = "0.8.0" diff --git a/check/tests/fail.rs b/check/tests/fail.rs index ad657cdca0..1529ff6caf 100644 --- a/check/tests/fail.rs +++ b/check/tests/fail.rs @@ -401,8 +401,10 @@ Types do not match: Expected: Int -> a Found: () - :2:4 + | 2 | () 1 | ^ + | - Attempted to call a non-function value "# ); @@ -429,8 +431,10 @@ Row labels do not match. Expected: A Found: B - :5:11 + | 5 | eq (A 0) (B 0.0) | ^^^^^ + | "# ); } @@ -454,8 +458,10 @@ Found: { x : Int } 1 errors were found during unification: The type `()` lacks the following fields: x - :4:7 + | 4 | f { } { x = 1 } | ^^^^^^^^^ + | "# ); } @@ -482,8 +488,10 @@ f (Test (Test 1)) &*format!("{}", result.unwrap_err()).replace("\t", " "), r#"error: Implicit parameter with type `test.Eq Int` could not be resolved. - :11:3 + | 11 | f (Test (Test 1)) | ^^^^^^^^^^^^^^^ + | - Required because of an implicit parameter of `[test.Eq Int] -> test.Eq (test.Test Int)` - Required because of an implicit parameter of `[test.Eq (test.Test Int)] -> test.Eq (test.Test (test.Test Int))` "#, @@ -704,8 +712,10 @@ Types do not match: Expected: Int -> Float -> a Found: String - :3:7 + | 3 | id "" 1 1.0 | ^^^^^ + | - Attempted to call function with 3 arguments but its type only has 1 "# ); @@ -738,8 +748,10 @@ Types do not match: Expected: Int -> Int -> a Found: test.Eff [| | r |] Int - :10:3 + | 10 | f x 1 | ^ + | "# ); } diff --git a/completion/Cargo.toml b/completion/Cargo.toml index 1b2bc83d6e..000249575f 100644 --- a/completion/Cargo.toml +++ b/completion/Cargo.toml @@ -15,7 +15,7 @@ documentation = "https://docs.rs/gluon" either = "1.0.0" itertools = "0.8" walkdir = "2" -codespan = "0.2" +codespan = "0.3" gluon_base = { path = "../base", version = "0.11.2" } # GLUON diff --git a/format/Cargo.toml b/format/Cargo.toml index bf705f334e..f7540573db 100644 --- a/format/Cargo.toml +++ b/format/Cargo.toml @@ -15,7 +15,7 @@ documentation = "https://docs.rs/gluon" log = "0.4" pretty = "0.5" itertools = "0.8" -codespan = "0.2" +codespan = "0.3" gluon_base = { path = "../base", version = "0.11.2" } # GLUON diff --git a/parser/Cargo.toml b/parser/Cargo.toml index 8a060b7696..6a6bbf910c 100644 --- a/parser/Cargo.toml +++ b/parser/Cargo.toml @@ -22,8 +22,8 @@ log = "0.4" pretty = "0.5" gluon_base = { path = "../base", version = "0.11.2" } # GLUON ordered-float = "1" -codespan = "0.2" -codespan-reporting = "0.2" +codespan = "0.3" +codespan-reporting = "0.3" [dev-dependencies] env_logger = "0.6" diff --git a/repl/Cargo.toml b/repl/Cargo.toml index 1950b38da7..dfb2691efc 100644 --- a/repl/Cargo.toml +++ b/repl/Cargo.toml @@ -37,8 +37,8 @@ env_logger = { version = "0.6", optional = true } lazy_static = "0.2.0" rustyline = "1.0.0" walkdir = "2" -codespan = "0.2" -codespan-reporting = "0.2" +codespan = "0.3" +codespan-reporting = "0.3" serde = "1" diff --git a/tests/ui.rs b/tests/ui.rs index 826b76456e..3103c25e8b 100644 --- a/tests/ui.rs +++ b/tests/ui.rs @@ -14,8 +14,10 @@ fn macro_error_with_line_column_info() { .unwrap(), r#"error: Could not find module 'undefined'. Searched `.`. - :1:9 + | 1 | import! undefined | ^^^^^^^^^ + | "# ); } diff --git a/vm/Cargo.toml b/vm/Cargo.toml index 77eb48dd8a..0a5e548158 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -14,18 +14,19 @@ documentation = "https://docs.rs/gluon" build = "build.rs" [dependencies] +bitflags = "1.0.0" +codespan = "0.3" +collect-mac = "0.1.0" frunk_core = "0.2" +futures = "0.1.0" +itertools = "0.8" log = "0.4" -quick-error = "1.1.0" mopa = "0.2.2" -collect-mac = "0.1.0" +ordered-float = "1" pretty = "0.5" -bitflags = "1.0.0" -itertools = "0.8" -futures = "0.1.0" -typed-arena = "1.2.0" +quick-error = "1.1.0" smallvec = "0.6" -codespan = "0.2" +typed-arena = "1.2.0" serde = { version = "1.0.0", optional = true } serde_json = { version = "1.0.0", optional = true } diff --git a/vm/src/compiler.rs b/vm/src/compiler.rs index c6709d2c33..ece4f7df96 100644 --- a/vm/src/compiler.rs +++ b/vm/src/compiler.rs @@ -1,7 +1,7 @@ use std::ops::{Deref, DerefMut}; use crate::base::{ - ast::{self, DisplayEnv, Literal, Typed, TypedIdent}, + ast::{DisplayEnv, Typed, TypedIdent}, kind::{ArcKind, KindEnv}, pos::Line, resolve, @@ -12,7 +12,7 @@ use crate::base::{ }; use crate::{ - core::{self, CExpr, Expr, Pattern}, + core::{self, CExpr, Expr, Literal, Pattern}, interner::InternedStr, source_map::{LocalMap, SourceMap}, types::*, @@ -815,27 +815,27 @@ impl<'a> Compiler<'a> { Pattern::Literal(ref l) => { let lhs_i = function.stack_size() - 1; match *l { - ast::Literal::Byte(b) => { + Literal::Byte(b) => { function.emit(Push(lhs_i)); function.emit(PushByte(b)); function.emit(ByteEQ); } - ast::Literal::Int(i) => { + Literal::Int(i) => { function.emit(Push(lhs_i)); function.emit(PushInt(i)); function.emit(IntEQ); } - ast::Literal::Char(ch) => { + Literal::Char(ch) => { function.emit(Push(lhs_i)); function.emit(PushInt(u32::from(ch).into())); function.emit(IntEQ); } - ast::Literal::Float(f) => { + Literal::Float(f) => { function.emit(Push(lhs_i)); function.emit(PushFloat(f.into_inner())); function.emit(FloatEQ); } - ast::Literal::String(ref s) => { + Literal::String(ref s) => { self.load_identifier(&Symbol::from("@string_eq"), function)?; let lhs_i = function.stack_size() - 2; function.emit(Push(lhs_i)); diff --git a/vm/src/core/grammar.lalrpop b/vm/src/core/grammar.lalrpop index c9ebe91fad..a58beda0c2 100644 --- a/vm/src/core/grammar.lalrpop +++ b/vm/src/core/grammar.lalrpop @@ -1,10 +1,10 @@ use crate::base::{ - ast::{Literal, TypedIdent}, + ast::{TypedIdent}, pos::{BytePos, Span}, symbol::{Symbol, Symbols}, types::{Field, Type}}; -use crate::core::{Allocator, Alternative, Closure, Expr, LetBinding, Named, Pattern}; +use crate::core::{Allocator, Alternative, Closure, Expr, LetBinding, Literal, Named, Pattern}; grammar<'env, 'a>(symbols: &'env mut Symbols, allocator: &'a Allocator<'a>); @@ -27,7 +27,7 @@ Field: (Symbol, Option) = { Literal: Literal = { => Literal::Int(<>.parse().unwrap()), - => Literal::String(<>[1..<>.len() - 1].to_string()), + => Literal::String(Box::from(&<>[1..<>.len() - 1])), }; Pattern: Pattern = { @@ -122,7 +122,7 @@ pub Expr: Expr<'a> = { } }, "in" => { - Expr::Let(bind, expr) + Expr::Let(allocator.let_binding_arena.alloc(bind), expr) }, "match" "with" "end" => Expr::Match(expr, allocator.alternative_arena.alloc_extend(alts.into_iter())), diff --git a/vm/src/core/interpreter.rs b/vm/src/core/interpreter.rs index cf82814864..f24766aa09 100644 --- a/vm/src/core/interpreter.rs +++ b/vm/src/core/interpreter.rs @@ -1,7 +1,7 @@ use std::ops::{Deref, DerefMut}; use crate::base::{ - ast::{Literal, TypedIdent}, + ast::TypedIdent, fnv::FnvSet, kind::{ArcKind, KindEnv}, merge::merge_iter, @@ -14,7 +14,7 @@ use crate::{ core::{ self, optimize::{walk_expr_alloc, DifferentLifetime, ExprProducer, SameLifetime, Visitor}, - Allocator, CExpr, Closure, Expr, LetBinding, Named, Pattern, + Allocator, CExpr, Closure, Expr, LetBinding, Literal, Named, Pattern, }, types::*, Error, Result, @@ -443,7 +443,7 @@ impl<'a, 'e> Compiler<'a, 'e> { }; if variable_in_value { value = Some(Reduced::Local(&*self.allocator.arena.alloc(Expr::Let( - bind, + self.allocator.let_binding_arena.alloc(bind), value.map_or(expr, |value| value.into_local(allocator)), )))); } @@ -524,7 +524,7 @@ impl<'a, 'e> Compiler<'a, 'e> { if let Some(expr) = new_named { self.bindings.push(LetBinding { expr, - ..let_binding.clone() + ..(*let_binding).clone() }); } return Ok(TailCall::Tail(body)); diff --git a/vm/src/core/mod.rs b/vm/src/core/mod.rs index 5c3d4f8d53..e3fbc3744c 100644 --- a/vm/src/core/mod.rs +++ b/vm/src/core/mod.rs @@ -40,16 +40,15 @@ mod pretty; use std::{borrow::Cow, cell::RefCell, collections::HashMap, fmt, iter::once, mem}; -use itertools::Itertools; +use {itertools::Itertools, ordered_float::NotNan, smallvec::SmallVec}; use self::{ optimize::{walk_expr_alloc, SameLifetime, Visitor}, - smallvec::SmallVec, typed_arena::Arena, }; use crate::base::{ - ast::{self, Literal, SpannedExpr, SpannedPattern, Typed, TypedIdent}, + ast::{self, SpannedExpr, SpannedPattern, Typed, TypedIdent}, fnv::{FnvMap, FnvSet}, pos::{spanned, BytePos, Span, Spanned}, resolve::remove_aliases_cow, @@ -57,6 +56,12 @@ use crate::base::{ types::{arg_iter, ArcType, NullInterner, PrimitiveEnv, Type, TypeEnv, TypeExt}, }; +macro_rules! iterator { + ($($expr : expr),* $(,)?) => { + [$(Some($expr)),*].iter_mut().map(|e| e.take().unwrap()) + } +} + #[derive(Clone, Debug, PartialEq)] pub struct Closure<'a> { pub pos: BytePos, @@ -78,15 +83,24 @@ pub struct LetBinding<'a> { pub span_start: BytePos, } +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub enum Literal { + Byte(u8), + Int(i64), + Float(NotNan), + String(Box), + Char(char), +} + #[derive(Clone, Debug, PartialEq)] pub enum Pattern { Constructor(TypedIdent, Vec>), Record(Vec<(TypedIdent, Option)>), Ident(TypedIdent), - Literal(ast::Literal), + Literal(Literal), } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Default, PartialEq)] pub struct Alternative<'a> { pub pattern: Pattern, pub expr: &'a Expr<'a>, @@ -98,10 +112,10 @@ pub type CExpr<'a> = &'a Expr<'a>; pub enum Expr<'a> { Const(Literal, Span), Ident(TypedIdent, Span), - Call(&'a Expr<'a>, &'a [Expr<'a>]), + Call(CExpr<'a>, &'a [Expr<'a>]), Data(TypedIdent, &'a [Expr<'a>], BytePos), - Let(LetBinding<'a>, &'a Expr<'a>), - Match(&'a Expr<'a>, &'a [Alternative<'a>]), + Let(&'a LetBinding<'a>, CExpr<'a>), + Match(CExpr<'a>, &'a [Alternative<'a>]), } #[cfg(feature = "test")] @@ -140,6 +154,58 @@ impl<'a> fmt::Display for Expr<'a> { } } +impl Default for &'static Expr<'static> { + fn default() -> Self { + static X: Expr<'static> = + Expr::Const(Literal::Int(0), Span::new_unchecked(BytePos(0), BytePos(0))); + &X + } +} + +impl<'a> Default for Expr<'a> { + fn default() -> Self { + Expr::Const(Literal::default(), Span::default()) + } +} + +impl Default for Pattern { + fn default() -> Self { + Pattern::Literal(Literal::default()) + } +} + +impl Literal { + fn from_ast(literal: &ast::Literal) -> Self { + match literal { + ast::Literal::Byte(x) => Literal::Byte(*x), + ast::Literal::Int(x) => Literal::Int(*x), + ast::Literal::Float(x) => Literal::Float(*x), + ast::Literal::String(x) => Literal::String(Box::from(&x[..])), + ast::Literal::Char(x) => Literal::Char(*x), + } + } +} + +impl Default for Literal { + fn default() -> Self { + Literal::Int(0) + } +} + +impl Typed for Literal { + type Ident = Symbol; + + fn try_type_of(&self, _: &TypeEnv) -> Result { + Ok(match *self { + Literal::Int(_) => Type::int(), + Literal::Float(_) => Type::float(), + Literal::Byte(_) => Type::byte(), + Literal::String(_) => Type::string(), + Literal::Char(_) => Type::char(), + }) + } +} + #[derive(Default)] #[must_use] struct Binder<'a> { @@ -165,18 +231,21 @@ impl<'a> Binder<'a> { ident_expr } - fn into_expr(self, arena: &'a Arena>, expr: Expr<'a>) -> Expr<'a> { - self.bindings - .into_iter() - .rev() - .fold(expr, |expr, bind| Expr::Let(bind, arena.alloc(expr))) + fn into_expr(self, allocator: &'a Allocator<'a>, expr: Expr<'a>) -> Expr<'a> { + self.bindings.into_iter().rev().fold(expr, |expr, bind| { + Expr::Let( + allocator.let_binding_arena.alloc(bind), + allocator.arena.alloc(expr), + ) + }) } - fn into_expr_ref(self, arena: &'a Arena>, expr: &'a Expr<'a>) -> &'a Expr<'a> { - self.bindings - .into_iter() - .rev() - .fold(expr, |expr, bind| arena.alloc(Expr::Let(bind, expr))) + fn into_expr_ref(self, allocator: &'a Allocator<'a>, expr: &'a Expr<'a>) -> &'a Expr<'a> { + self.bindings.into_iter().rev().fold(expr, |expr, bind| { + allocator + .arena + .alloc(Expr::Let(allocator.let_binding_arena.alloc(bind), expr)) + }) } } @@ -242,6 +311,7 @@ pub use self::internal::CoreExpr; pub struct Allocator<'a> { pub arena: Arena>, pub alternative_arena: Arena>, + pub let_binding_arena: Arena>, } impl<'a> Allocator<'a> { @@ -249,6 +319,64 @@ impl<'a> Allocator<'a> { Allocator { arena: Arena::new(), alternative_arena: Arena::new(), + let_binding_arena: Arena::new(), + } + } +} + +pub(crate) trait ArenaExt { + fn alloc_fixed<'a, I>(&'a self, iter: I) -> &'a mut [T] + where + I: IntoIterator, + T: Default; +} + +impl ArenaExt for Arena { + fn alloc_fixed<'a, I>(&'a self, iter: I) -> &'a mut [T] + where + I: IntoIterator, + T: Default, + { + use std::ptr; + + let iter = iter.into_iter(); + + unsafe { + struct FillRemainingOnDrop { + ptr: *mut U, + end: *mut U, + } + + impl Drop for FillRemainingOnDrop { + fn drop(&mut self) { + unsafe { + while self.ptr != self.end { + ptr::write(self.ptr, U::default()); + self.ptr = self.ptr.add(1); + } + } + } + } + let (len, max) = iter.size_hint(); + assert!(Some(len) == max); + + let elems = self.alloc_uninitialized(len); + + { + let elems = elems as *mut T; + let mut fill = FillRemainingOnDrop { + ptr: elems as *mut T, + end: elems.add(len) as *mut T, + }; + + for elem in iter { + assert!(fill.ptr != fill.end); + ptr::write(fill.ptr, elem); + fill.ptr = fill.ptr.add(1); + } + } + + &mut *elems } } } @@ -385,35 +513,30 @@ impl<'a, 'e> Translator<'a, 'e> { func: ref function, ref args, } => { - let new_args: SmallVec<[_; 16]> = implicit_args + let all_args = implicit_args .iter() .chain(args) - .map(|arg| self.translate(arg)) - .collect(); + .map(|arg| self.translate(arg)); match function.value { ast::Expr::Ident(ref id) if is_constructor(&id.name) => { let typ = expr.env_type_of(&self.env); - self.new_data_constructor(typ, id, new_args, expr.span) + self.new_data_constructor(typ, id, all_args, expr.span) + } + _ => { + let new_args = &*arena.alloc_fixed(all_args); + Expr::Call(self.translate_alloc(function), new_args) } - _ => Expr::Call( - self.translate_alloc(function), - arena.alloc_extend(new_args.into_iter()), - ), } } ast::Expr::Array(ref array) => { - let exprs: SmallVec<[_; 16]> = array - .exprs - .iter() - .map(|expr| self.translate(expr)) - .collect(); + let exprs = arena.alloc_fixed(array.exprs.iter().map(|expr| self.translate(expr))); Expr::Data( TypedIdent { name: self.dummy_symbol.name.clone(), typ: array.typ.clone(), }, - arena.alloc_extend(exprs.into_iter()), + exprs, expr.span.start(), ) } @@ -423,11 +546,11 @@ impl<'a, 'e> Translator<'a, 'e> { let result = self.translate(last); prefix.iter().rev().fold(result, |result, expr| { Expr::Let( - LetBinding { + self.allocator.let_binding_arena.alloc(LetBinding { name: self.dummy_symbol.clone(), expr: Named::Expr(self.translate_alloc(expr)), span_start: expr.span.start(), - }, + }), arena.alloc(result), ) }) @@ -435,7 +558,7 @@ impl<'a, 'e> Translator<'a, 'e> { ast::Expr::Ident(ref id) => { if is_constructor(&id.name) { - self.new_data_constructor(id.typ.clone(), id, SmallVec::new(), expr.span) + self.new_data_constructor(id.typ.clone(), id, &mut None.into_iter(), expr.span) } else { let name = self .ident_replacements @@ -455,7 +578,7 @@ impl<'a, 'e> Translator<'a, 'e> { } ast::Expr::IfElse(ref pred, ref if_true, ref if_false) => { - let alts: SmallVec<[_; 2]> = collect![ + let alts = self.allocator.alternative_arena.alloc_fixed(iterator!( Alternative { pattern: Pattern::Constructor(self.bool_constructor(true), vec![]), expr: self.translate_alloc(if_true), @@ -464,13 +587,8 @@ impl<'a, 'e> Translator<'a, 'e> { pattern: Pattern::Constructor(self.bool_constructor(false), vec![]), expr: self.translate_alloc(if_false), }, - ]; - Expr::Match( - self.translate_alloc(pred), - self.allocator - .alternative_arena - .alloc_extend(alts.into_iter()), - ) + )); + Expr::Match(self.translate_alloc(pred), alts) } ast::Expr::Infix { @@ -479,17 +597,14 @@ impl<'a, 'e> Translator<'a, 'e> { ref rhs, ref implicit_args, } => { - let args: SmallVec<[_; 2]> = implicit_args - .iter() - .chain(Some(&**lhs)) - .chain(Some(&**rhs)) - .map(|e| self.translate(e)) - .collect(); + let args = arena.alloc_fixed( + implicit_args + .iter() + .chain(iterator!(&**lhs, &**rhs)) + .map(|e| self.translate(e)), + ); - Expr::Call( - arena.alloc(Expr::Ident(op.value.clone(), op.span)), - arena.alloc_extend(args.into_iter()), - ) + Expr::Call(arena.alloc(Expr::Ident(op.value.clone(), op.span)), args) } ast::Expr::Lambda(ref lambda) => self.new_lambda( @@ -508,7 +623,7 @@ impl<'a, 'e> Translator<'a, 'e> { self.translate_let(binds, self.translate(tail), expr.span.start()) } - ast::Expr::Literal(ref literal) => Expr::Const(literal.clone(), expr.span), + ast::Expr::Literal(ref literal) => Expr::Const(Literal::from_ast(literal), expr.span), ast::Expr::Match(ref expr, ref alts) => { let expr = self.translate_alloc(expr); @@ -618,24 +733,23 @@ impl<'a, 'e> Translator<'a, 'e> { name: self.dummy_symbol.name.clone(), typ: typ.clone(), }, - arena.alloc_extend(args), + arena.alloc_fixed(args), expr.span.start(), ); - binder.into_expr(arena, record_constructor) + binder.into_expr(&self.allocator, record_constructor) } ast::Expr::Tuple { ref elems, .. } => { if elems.len() == 1 { self.translate(&elems[0]) } else { - let args: SmallVec<[_; 16]> = - elems.iter().map(|expr| self.translate(expr)).collect(); + let args = arena.alloc_fixed(elems.iter().map(|expr| self.translate(expr))); Expr::Data( TypedIdent { name: self.dummy_symbol.name.clone(), typ: expr.env_type_of(&self.env), }, - arena.alloc_extend(args.into_iter()), + args, expr.span.start(), ) } @@ -698,10 +812,10 @@ impl<'a, 'e> Translator<'a, 'e> { let f = self.translate_alloc(flat_map_id); binder.into_expr( - arena, + &self.allocator, Expr::Call( f, - arena.alloc_extend(Some(lambda).into_iter().chain(Some(bound_ident))), + arena.alloc_fixed(Some(lambda).into_iter().chain(Some(bound_ident))), ), ) } @@ -742,7 +856,7 @@ impl<'a, 'e> Translator<'a, 'e> { }; Expr::Match( projected_expr, - self.allocator.alternative_arena.alloc_extend(once(alt)), + self.allocator.alternative_arena.alloc_fixed(once(alt)), ) } @@ -768,12 +882,12 @@ impl<'a, 'e> Translator<'a, 'e> { }) .collect(); Expr::Let( - LetBinding { + self.allocator.let_binding_arena.alloc(LetBinding { // TODO name: self.dummy_symbol.clone(), expr: Named::Recursive(closures), span_start: span_start, - }, + }), arena.alloc(tail), ) } else { @@ -803,11 +917,11 @@ impl<'a, 'e> Translator<'a, 'e> { }]) }; Expr::Let( - LetBinding { + self.allocator.let_binding_arena.alloc(LetBinding { name: name, expr: named, span_start: bind.expr.span.start(), - }, + }), arena.alloc(tail), ) }) @@ -837,7 +951,17 @@ impl<'a, 'e> Translator<'a, 'e> { &'a self, expr_type: ArcType, id: &TypedIdent, - mut new_args: SmallVec<[Expr<'a>; 16]>, + new_args: impl IntoIterator>, + span: Span, + ) -> Expr<'a> { + self.new_data_constructor_(expr_type, id, &mut new_args.into_iter(), span) + } + + fn new_data_constructor_( + &'a self, + expr_type: ArcType, + id: &TypedIdent, + new_args: &mut Iterator>, span: Span, ) -> Expr<'a> { let arena = &self.allocator.arena; @@ -860,7 +984,7 @@ impl<'a, 'e> Translator<'a, 'e> { .collect(); data_type = args.typ.clone(); } - new_args.extend( + let new_args = new_args.chain( unapplied_args .iter() .map(|arg| Expr::Ident(arg.clone(), span)), @@ -870,7 +994,7 @@ impl<'a, 'e> Translator<'a, 'e> { name: id.name.clone(), typ: data_type, }, - arena.alloc_extend(new_args.into_iter()), + arena.alloc_fixed(new_args), span.start(), ); if unapplied_args.is_empty() { @@ -899,7 +1023,7 @@ impl<'a, 'e> Translator<'a, 'e> { ) -> Expr<'a> { let arena = &self.allocator.arena; Expr::Let( - LetBinding { + self.allocator.let_binding_arena.alloc(LetBinding { name: name.clone(), expr: Named::Recursive(vec![Closure { pos, @@ -908,7 +1032,7 @@ impl<'a, 'e> Translator<'a, 'e> { expr: body, }]), span_start: span.start(), - }, + }), arena.alloc(Expr::Ident(name, span)), ) } @@ -919,7 +1043,7 @@ impl<'a, 'e> Translator<'a, 'e> { TypedIdent::new(Symbol::from("@error")), Span::default(), )); - let args = arena.alloc_extend( + let args = arena.alloc_fixed( Some(Expr::Const(Literal::String(msg.into()), Span::default())).into_iter(), ); Expr::Call(error, args) @@ -1131,7 +1255,7 @@ impl<'a, 'e> PatternTranslator<'a, 'e> { self.0 .allocator .alternative_arena - .alloc_extend(Some(new_alt).into_iter()), + .alloc_fixed(Some(new_alt).into_iter()), ); self.0.allocator.arena.alloc(expr) } @@ -1225,7 +1349,7 @@ impl<'a, 'e> PatternTranslator<'a, 'e> { self.0 .allocator .alternative_arena - .alloc_extend(new_alts.into_iter()), + .alloc_fixed(new_alts.into_iter()), ); self.0.allocator.arena.alloc(expr) } @@ -1263,7 +1387,7 @@ impl<'a, 'e> PatternTranslator<'a, 'e> { self.0 .allocator .alternative_arena - .alloc_extend(Some(alt).into_iter()), + .alloc_fixed(Some(alt).into_iter()), ); self.0.allocator.arena.alloc(expr) } @@ -1301,7 +1425,7 @@ impl<'a, 'e> PatternTranslator<'a, 'e> { .into_iter() .map(|key| { let equations = &groups[key]; - let pattern = Pattern::Literal(key.clone()); + let pattern = Pattern::Literal(Literal::from_ast(key)); let new_equations = equations .iter() @@ -1329,7 +1453,7 @@ impl<'a, 'e> PatternTranslator<'a, 'e> { self.0 .allocator .alternative_arena - .alloc_extend(new_alts.into_iter()), + .alloc_fixed(new_alts.into_iter()), ); self.0.allocator.arena.alloc(expr) } @@ -1373,11 +1497,11 @@ impl<'a, 'e> PatternTranslator<'a, 'e> { .arena .alloc(Expr::Ident(name.clone(), expr.span())); Expr::Let( - LetBinding { + self.0.allocator.let_binding_arena.alloc(LetBinding { name: name, expr: Named::Expr(expr), span_start: expr.span().start(), - }, + }), self.translate(default, &[id_expr], equations), ) } @@ -1479,8 +1603,8 @@ impl<'a, 'e> PatternTranslator<'a, 'e> { equations.iter().format(",\n"), expr ); - let arena = &self.0.allocator.arena; - binder.into_expr_ref(arena, expr) + let allocator = &self.0.allocator; + binder.into_expr_ref(allocator, expr) } fn extract_ident(&self, index: usize, pattern: &ast::Pattern) -> TypedIdent { @@ -2207,4 +2331,10 @@ mod tests { "#; check_translation(expr_str, expected_str); } + + #[test] + fn expr_size() { + let s = std::mem::size_of::(); + assert!(s <= 40, "{} is to large for expressions", s); + } } diff --git a/vm/src/core/optimize.rs b/vm/src/core/optimize.rs index 07be7f4639..96b4eb5bd6 100644 --- a/vm/src/core/optimize.rs +++ b/vm/src/core/optimize.rs @@ -110,14 +110,14 @@ impl<'a> Visitor<'a, 'a> for RecognizeUnnecessaryAllocation<'a> { }) .unwrap_or_else(|| Symbol::from("dummy")); let new_expr = Expr::Let( - LetBinding { + self_.allocator.let_binding_arena.alloc(LetBinding { name: TypedIdent { name: pattern_field.clone(), typ: field.typ.clone(), }, expr: Named::Expr(expr), span_start: pos::BytePos::default(), - }, + }), next_expr, ); &*self_.allocator().arena.alloc(new_expr) @@ -279,7 +279,7 @@ where } } -fn walk_bind<'a, 'b, V>(visitor: &mut V, bind: &LetBinding<'b>) -> Option> +fn walk_bind<'a, 'b, V>(visitor: &mut V, bind: &LetBinding<'b>) -> Option<&'a LetBinding<'a>> where V: ?Sized + Visitor<'a, 'b>, { @@ -305,10 +305,15 @@ where .map(Named::Recursive), Named::Expr(bind_expr) => visitor.visit_expr(bind_expr).map(Named::Expr), }; - new_named.map(|named| LetBinding { - name: bind.name.clone(), - expr: named, - span_start: bind.span_start, + new_named.map(|named| { + &*allocator + .expect("Allocator") + .let_binding_arena + .alloc(LetBinding { + name: bind.name.clone(), + expr: named, + span_start: bind.span_start, + }) }) }