Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

Fix impl tracking bug

+333 -73
+30 -6
compiler-core/generated/schema_capnp.rs
··· 2840 2840 self.reader.get_bool_field(0) 2841 2841 } 2842 2842 #[inline] 2843 - pub fn get_erlang(self) -> bool { 2843 + pub fn get_uses_erlang_externals(self) -> bool { 2844 2844 self.reader.get_bool_field(1) 2845 2845 } 2846 2846 #[inline] 2847 - pub fn get_javascript(self) -> bool { 2847 + pub fn get_uses_javascript_externals(self) -> bool { 2848 2848 self.reader.get_bool_field(2) 2849 + } 2850 + #[inline] 2851 + pub fn get_can_run_on_erlang(self) -> bool { 2852 + self.reader.get_bool_field(3) 2853 + } 2854 + #[inline] 2855 + pub fn get_can_run_on_javascript(self) -> bool { 2856 + self.reader.get_bool_field(4) 2849 2857 } 2850 2858 } 2851 2859 ··· 2906 2914 self.builder.set_bool_field(0, value); 2907 2915 } 2908 2916 #[inline] 2909 - pub fn get_erlang(self) -> bool { 2917 + pub fn get_uses_erlang_externals(self) -> bool { 2910 2918 self.builder.get_bool_field(1) 2911 2919 } 2912 2920 #[inline] 2913 - pub fn set_erlang(&mut self, value: bool) { 2921 + pub fn set_uses_erlang_externals(&mut self, value: bool) { 2914 2922 self.builder.set_bool_field(1, value); 2915 2923 } 2916 2924 #[inline] 2917 - pub fn get_javascript(self) -> bool { 2925 + pub fn get_uses_javascript_externals(self) -> bool { 2918 2926 self.builder.get_bool_field(2) 2919 2927 } 2920 2928 #[inline] 2921 - pub fn set_javascript(&mut self, value: bool) { 2929 + pub fn set_uses_javascript_externals(&mut self, value: bool) { 2922 2930 self.builder.set_bool_field(2, value); 2931 + } 2932 + #[inline] 2933 + pub fn get_can_run_on_erlang(self) -> bool { 2934 + self.builder.get_bool_field(3) 2935 + } 2936 + #[inline] 2937 + pub fn set_can_run_on_erlang(&mut self, value: bool) { 2938 + self.builder.set_bool_field(3, value); 2939 + } 2940 + #[inline] 2941 + pub fn get_can_run_on_javascript(self) -> bool { 2942 + self.builder.get_bool_field(4) 2943 + } 2944 + #[inline] 2945 + pub fn set_can_run_on_javascript(&mut self, value: bool) { 2946 + self.builder.set_bool_field(4, value); 2923 2947 } 2924 2948 } 2925 2949
+5 -3
compiler-core/schema.capnp
··· 106 106 107 107 struct Implementations { 108 108 gleam @0 :Bool; 109 - erlang @1 :Bool; 110 - javascript @2 :Bool; 109 + usesErlangExternals @1 :Bool; 110 + usesJavascriptExternals @2 :Bool; 111 + canRunOnErlang @3 :Bool; 112 + canRunOnJavascript @4 :Bool; 111 113 } 112 114 113 115 struct ValueConstructorVariant { ··· 245 247 struct LineNumbers { 246 248 lineStarts @0 :List(UInt32); 247 249 length @1 :UInt32; 248 - } 250 + }
+10 -8
compiler-core/src/analyse.rs
··· 18 18 self, 19 19 environment::*, 20 20 error::{convert_unify_error, Error, MissingAnnotation}, 21 - expression::{ExprTyper, Externals}, 21 + expression::{ExprTyper, FunctionDefinition}, 22 22 fields::{FieldMap, FieldMapBuilder}, 23 23 hydrator::Hydrator, 24 24 prelude::*, ··· 691 691 ensure_annotations_present(&arguments, return_annotation.as_ref(), location)?; 692 692 } 693 693 694 - let externals = Externals { 695 - erlang: external_erlang.is_some(), 696 - javascript: external_javascript.is_some(), 694 + let definition = FunctionDefinition { 695 + has_body: !body.first().is_placeholder(), 696 + has_erlang_external: external_erlang.is_some(), 697 + has_javascript_external: external_javascript.is_some(), 697 698 }; 698 699 699 700 // Infer the type using the preregistered args + return types as a starting point ··· 703 704 .zip(&args_types) 704 705 .map(|(a, t)| a.set_type(t.clone())) 705 706 .collect(); 706 - let mut expr_typer = ExprTyper::new(environment, externals); 707 + let mut expr_typer = ExprTyper::new(environment, definition); 707 708 expr_typer.hydrator = hydrators 708 709 .remove(&name) 709 710 .expect("Could not find hydrator for fn"); ··· 1016 1017 1017 1018 let mut expr_typer = ExprTyper::new( 1018 1019 environment, 1019 - Externals { 1020 - erlang: false, 1021 - javascript: false, 1020 + FunctionDefinition { 1021 + has_body: true, 1022 + has_erlang_external: false, 1023 + has_javascript_external: false, 1022 1024 }, 1023 1025 ); 1024 1026 let typed_expr = expr_typer.infer_const(&annotation, *value)?;
+5 -4
compiler-core/src/ast/tests.rs
··· 3 3 use crate::analyse::TargetSupport; 4 4 use crate::build::Target; 5 5 use crate::line_numbers::LineNumbers; 6 - use crate::type_::expression::Externals; 6 + use crate::type_::expression::FunctionDefinition; 7 7 use crate::type_::{Deprecation, PRELUDE_MODULE_NAME}; 8 8 use crate::{ 9 9 ast::{SrcSpan, TypedExpr}, ··· 132 132 ); 133 133 ExprTyper::new( 134 134 &mut environment, 135 - Externals { 136 - erlang: false, 137 - javascript: false, 135 + FunctionDefinition { 136 + has_body: true, 137 + has_erlang_external: false, 138 + has_javascript_external: false, 138 139 }, 139 140 ) 140 141 .infer_statements(ast)
+4
compiler-core/src/call_graph/into_dependency_order_tests.rs
··· 41 41 gleam: true, 42 42 uses_erlang_externals: true, 43 43 uses_javascript_externals: false, 44 + can_run_on_erlang: true, 45 + can_run_on_javascript: true, 44 46 }, 45 47 }) 46 48 .collect_vec(); ··· 59 61 gleam: true, 60 62 uses_erlang_externals: true, 61 63 uses_javascript_externals: false, 64 + can_run_on_erlang: true, 65 + can_run_on_javascript: true, 62 66 }, 63 67 type_: (), 64 68 deprecation: Deprecation::NotDeprecated,
+38 -1
compiler-core/src/erlang/tests/external_fn.rs
··· 5 5 assert_erl!( 6 6 r#" 7 7 @external(erlang, "Elixir.MyApp", "run") 8 - pub fn run() -> Int 8 + pub fn run() -> Int 9 9 "# 10 10 ); 11 11 } ··· 279 279 "# 280 280 ); 281 281 } 282 + 283 + #[test] 284 + fn javascript_only_indirect() { 285 + assert_erl!( 286 + r#" 287 + pub fn should_be_generated(x: Int) -> Int { 288 + x 289 + } 290 + 291 + @external(javascript, "one", "one") 292 + pub fn should_not_be_generated(x: Int) -> Int 293 + 294 + pub fn also_should_not_be_generated() { 295 + should_not_be_generated(1) 296 + |> should_be_generated 297 + } 298 + "# 299 + ); 300 + } 301 + 302 + #[test] 303 + fn both_externals_no_valid_impl() { 304 + assert_erl!( 305 + r#" 306 + @external(javascript, "one", "one") 307 + pub fn js() -> Nil 308 + 309 + @external(erlang, "one", "one") 310 + pub fn erl() -> Nil 311 + 312 + pub fn should_not_be_generated() { 313 + js() 314 + erl() 315 + } 316 + "# 317 + ); 318 + }
+13
compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__external_fn__both_externals_no_valid_impl.snap
··· 1 + --- 2 + source: compiler-core/src/erlang/tests/external_fn.rs 3 + assertion_line: 304 4 + expression: "\n@external(javascript, \"one\", \"one\")\npub fn js() -> Nil\n\n@external(erlang, \"one\", \"one\")\npub fn erl() -> Nil\n\npub fn should_not_be_generated() {\n js()\n erl()\n}\n" 5 + --- 6 + -module(my@mod). 7 + -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). 8 + 9 + -export([erl/0]). 10 + 11 + -spec erl() -> nil. 12 + erl() -> 13 + one:one().
+13
compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__external_fn__javascript_only_indirect.snap
··· 1 + --- 2 + source: compiler-core/src/erlang/tests/external_fn.rs 3 + assertion_line: 285 4 + expression: "\npub fn should_be_generated(x: Int) -> Int {\n x\n}\n\n@external(javascript, \"one\", \"one\")\npub fn should_not_be_generated(x: Int) -> Int\n\npub fn also_should_not_be_generated() {\n should_not_be_generated(1)\n |> should_be_generated\n}\n" 5 + --- 6 + -module(my@mod). 7 + -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). 8 + 9 + -export([should_be_generated/1]). 10 + 11 + -spec should_be_generated(integer()) -> integer(). 12 + should_be_generated(X) -> 13 + X.
+18
compiler-core/src/javascript/tests/externals.rs
··· 286 286 "# 287 287 ); 288 288 } 289 + 290 + #[test] 291 + fn both_externals_no_valid_impl() { 292 + assert_js!( 293 + r#" 294 + @external(javascript, "one", "one") 295 + pub fn js() -> Nil 296 + 297 + @external(erlang, "one", "one") 298 + pub fn erl() -> Nil 299 + 300 + pub fn should_not_be_generated() { 301 + js() 302 + erl() 303 + } 304 + "# 305 + ); 306 + }
+8
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__externals__both_externals_no_valid_impl.snap
··· 1 + --- 2 + source: compiler-core/src/javascript/tests/externals.rs 3 + assertion_line: 292 4 + expression: "\n@external(javascript, \"one\", \"one\")\npub fn js() -> Nil\n\n@external(erlang, \"one\", \"one\")\npub fn erl() -> Nil\n\npub fn should_not_be_generated() {\n js()\n erl()\n}\n" 5 + --- 6 + import { one as js } from "one"; 7 + 8 + export { js };
+4 -2
compiler-core/src/metadata/module_decoder.rs
··· 473 473 fn implementations(&self, reader: implementations::Reader<'_>) -> Implementations { 474 474 Implementations { 475 475 gleam: reader.get_gleam(), 476 - uses_erlang_externals: reader.get_erlang(), 477 - uses_javascript_externals: reader.get_javascript(), 476 + uses_erlang_externals: reader.get_uses_erlang_externals(), 477 + uses_javascript_externals: reader.get_uses_javascript_externals(), 478 + can_run_on_erlang: reader.get_can_run_on_erlang(), 479 + can_run_on_javascript: reader.get_can_run_on_javascript(), 478 480 } 479 481 } 480 482
+4 -2
compiler-core/src/metadata/module_encoder.rs
··· 519 519 implementations: Implementations, 520 520 ) { 521 521 builder.set_gleam(implementations.gleam); 522 - builder.set_erlang(implementations.uses_erlang_externals); 523 - builder.set_javascript(implementations.uses_javascript_externals); 522 + builder.set_uses_erlang_externals(implementations.uses_erlang_externals); 523 + builder.set_uses_javascript_externals(implementations.uses_javascript_externals); 524 + builder.set_can_run_on_erlang(implementations.can_run_on_erlang); 525 + builder.set_can_run_on_javascript(implementations.can_run_on_javascript); 524 526 } 525 527 }
+22
compiler-core/src/metadata/tests.rs
··· 53 53 gleam: true, 54 54 uses_erlang_externals: false, 55 55 uses_javascript_externals: false, 56 + can_run_on_erlang: true, 57 + can_run_on_javascript: true, 56 58 }, 57 59 }, 58 60 }, ··· 376 378 gleam: true, 377 379 uses_erlang_externals: false, 378 380 uses_javascript_externals: false, 381 + can_run_on_erlang: true, 382 + can_run_on_javascript: true, 379 383 }, 380 384 }, 381 385 }, ··· 419 423 gleam: true, 420 424 uses_erlang_externals: false, 421 425 uses_javascript_externals: false, 426 + can_run_on_erlang: true, 427 + can_run_on_javascript: true, 422 428 }, 423 429 }, 424 430 }, ··· 460 466 gleam: true, 461 467 uses_erlang_externals: false, 462 468 uses_javascript_externals: false, 469 + can_run_on_erlang: true, 470 + can_run_on_javascript: true, 463 471 }, 464 472 }, 465 473 }, ··· 503 511 gleam: true, 504 512 uses_erlang_externals: false, 505 513 uses_javascript_externals: false, 514 + can_run_on_erlang: true, 515 + can_run_on_javascript: true, 506 516 }, 507 517 }, 508 518 }, ··· 545 555 gleam: true, 546 556 uses_erlang_externals: false, 547 557 uses_javascript_externals: false, 558 + can_run_on_erlang: true, 559 + can_run_on_javascript: true, 548 560 }, 549 561 }, 550 562 }, ··· 848 860 gleam: true, 849 861 uses_erlang_externals: false, 850 862 uses_javascript_externals: false, 863 + can_run_on_erlang: true, 864 + can_run_on_javascript: true, 851 865 }, 852 866 }, 853 867 })), ··· 878 892 gleam: true, 879 893 uses_erlang_externals: false, 880 894 uses_javascript_externals: false, 895 + can_run_on_erlang: true, 896 + can_run_on_javascript: true, 881 897 }, 882 898 }, 883 899 }, ··· 897 913 gleam: true, 898 914 uses_erlang_externals: false, 899 915 uses_javascript_externals: false, 916 + can_run_on_erlang: true, 917 + can_run_on_javascript: true, 900 918 }, 901 919 }, 902 920 }, ··· 1144 1162 gleam: false, 1145 1163 uses_erlang_externals: true, 1146 1164 uses_javascript_externals: true, 1165 + can_run_on_erlang: false, 1166 + can_run_on_javascript: true, 1147 1167 }, 1148 1168 }, 1149 1169 }, ··· 1186 1206 gleam: false, 1187 1207 uses_erlang_externals: true, 1188 1208 uses_javascript_externals: true, 1209 + can_run_on_erlang: true, 1210 + can_run_on_javascript: true, 1189 1211 }, 1190 1212 }, 1191 1213 },
+27 -4
compiler-core/src/package_interface.rs
··· 174 174 /// ```json 175 175 /// { 176 176 /// gleam: true, 177 + /// can_run_on_erlang: true, 178 + /// can_run_on_javascript: true, 177 179 /// uses_erlang_externals: true, 178 180 /// uses_javascript_externals: false, 179 181 /// } ··· 181 183 /// 182 184 /// - `gleam: true` means that the function has a pure Gleam implementation 183 185 /// and thus it can be used on all Gleam targets with no problems. 186 + /// - `can_run_on_erlang: false` the function can be called on the Erlang 187 + /// target. 188 + /// - `can_run_on_javascript: true` the function can be called on the JavaScript 189 + /// target. 184 190 /// - `uses_erlang_externals: true` means that the function will use Erlang 185 191 /// external code when compiled to the Erlang target. 186 192 /// - `uses_javascript_externals: false` means that the function won't use ··· 208 214 /// ```json 209 215 /// { 210 216 /// gleam: false, 217 + /// can_run_on_erlang: false, 218 + /// can_run_on_javascript: true, 211 219 /// uses_erlang_externals: false, 212 220 /// uses_javascript_externals: true, 213 221 /// } ··· 216 224 /// - `gleam: false` means that the function doesn't have a pure Gleam 217 225 /// implementations. This means that the function is only defined using 218 226 /// externals and can only be used on some targets. 227 + /// - `can_run_on_erlang: false` the function cannot be called on the Erlang 228 + /// target. 229 + /// - `can_run_on_javascript: true` the function can be called on the JavaScript 230 + /// target. 219 231 /// - `uses_erlang_externals: false` the function is not using external 220 - /// Erlang code. So, since the function doesn't have a fallback pure Gleam 221 - /// implementation, you won't be able to compile it on this target. 232 + /// Erlang code. 222 233 /// - `uses_javascript_externals: true` the function is using JavaScript 223 - /// external code. This means that you will be able to use it on the 224 - /// JavaScript target with no problems. 234 + /// external code. 225 235 uses_javascript_externals: bool, 236 + /// Whether the function can be called on the Erlang target, either due to a 237 + /// pure Gleam implementation or an implementation that uses some Erlang 238 + /// externals. 239 + can_run_on_erlang: bool, 240 + /// Whether the function can be called on the JavaScript target, either due 241 + /// to a pure Gleam implementation or an implementation that uses some 242 + /// JavaScript externals. 243 + can_run_on_javascript: bool, 226 244 } 227 245 228 246 impl ImplementationsInterface { ··· 240 258 gleam, 241 259 uses_erlang_externals, 242 260 uses_javascript_externals, 261 + 262 + can_run_on_erlang, 263 + can_run_on_javascript, 243 264 } = implementations; 244 265 245 266 ImplementationsInterface { 246 267 gleam: *gleam, 247 268 uses_erlang_externals: *uses_erlang_externals, 248 269 uses_javascript_externals: *uses_javascript_externals, 270 + can_run_on_erlang: *can_run_on_erlang, 271 + can_run_on_javascript: *can_run_on_javascript, 249 272 } 250 273 } 251 274 }
+4 -2
compiler-core/src/package_interface/snapshots/gleam_core__package_interface__tests__generic_function.snap
··· 1 1 --- 2 2 source: compiler-core/src/package_interface/tests.rs 3 - assertion_line: 220 3 + assertion_line: 236 4 4 expression: "\npub type Wob(a) { Wob }\n@deprecated(\"deprecation message\")\npub fn main() { Wob }\n" 5 5 --- 6 6 { ··· 35 35 "implementations": { 36 36 "gleam": true, 37 37 "uses-erlang-externals": false, 38 - "uses-javascript-externals": false 38 + "uses-javascript-externals": false, 39 + "can-run-on-erlang": true, 40 + "can-run-on-javascript": true 39 41 }, 40 42 "parameters": [], 41 43 "return": {
+4 -2
compiler-core/src/package_interface/snapshots/gleam_core__package_interface__tests__imported_aliased_type_keeps_original_name.snap
··· 1 1 --- 2 2 source: compiler-core/src/package_interface/tests.rs 3 - assertion_line: 242 3 + assertion_line: 258 4 4 expression: "\nimport other_module.{type Element as Alias} as module_alias\npub fn main() -> Alias(module_alias.Element(a)) {}\n" 5 5 --- 6 6 { ··· 20 20 "implementations": { 21 21 "gleam": true, 22 22 "uses-erlang-externals": false, 23 - "uses-javascript-externals": false 23 + "uses-javascript-externals": false, 24 + "can-run-on-erlang": true, 25 + "can-run-on-javascript": true 24 26 }, 25 27 "parameters": [], 26 28 "return": {
+4 -2
compiler-core/src/package_interface/snapshots/gleam_core__package_interface__tests__imported_type.snap
··· 1 1 --- 2 2 source: compiler-core/src/package_interface/tests.rs 3 - assertion_line: 231 3 + assertion_line: 247 4 4 expression: "\nimport other_module.{type Element}\npub fn main() -> Element(Int) {}\n" 5 5 --- 6 6 { ··· 20 20 "implementations": { 21 21 "gleam": true, 22 22 "uses-erlang-externals": false, 23 - "uses-javascript-externals": false 23 + "uses-javascript-externals": false, 24 + "can-run-on-erlang": true, 25 + "can-run-on-javascript": true 24 26 }, 25 27 "parameters": [], 26 28 "return": {
+4 -2
compiler-core/src/package_interface/snapshots/gleam_core__package_interface__tests__multiple_type_variables.snap
··· 1 1 --- 2 2 source: compiler-core/src/package_interface/tests.rs 3 - assertion_line: 253 3 + assertion_line: 269 4 4 expression: "\npub type Box(a, b)\npub fn some_type_variables(a: a, b: b, c: Box(c, d)) -> Box(a, d) {}\n" 5 5 --- 6 6 { ··· 27 27 "implementations": { 28 28 "gleam": true, 29 29 "uses-erlang-externals": false, 30 - "uses-javascript-externals": false 30 + "uses-javascript-externals": false, 31 + "can-run-on-erlang": true, 32 + "can-run-on-javascript": true 31 33 }, 32 34 "parameters": [ 33 35 {
+4 -2
compiler-core/src/package_interface/snapshots/gleam_core__package_interface__tests__package_documentation_is_included.snap
··· 1 1 --- 2 2 source: compiler-core/src/package_interface/tests.rs 3 - assertion_line: 161 3 + assertion_line: 165 4 4 expression: "\n//// Some package\n//// documentation!\n\npub fn main() { 1 }\n" 5 5 --- 6 6 { ··· 23 23 "implementations": { 24 24 "gleam": true, 25 25 "uses-erlang-externals": false, 26 - "uses-javascript-externals": false 26 + "uses-javascript-externals": false, 27 + "can-run-on-erlang": true, 28 + "can-run-on-javascript": true 27 29 }, 28 30 "parameters": [], 29 31 "return": {
+13 -5
compiler-core/src/package_interface/snapshots/gleam_core__package_interface__tests__prelude_types.snap
··· 1 1 --- 2 2 source: compiler-core/src/package_interface/tests.rs 3 - assertion_line: 208 3 + assertion_line: 224 4 4 expression: "\npub const float = 1.1\npub const string = \"\"\npub const int = 1\npub const bool = True\n" 5 5 --- 6 6 { ··· 19 19 "implementations": { 20 20 "gleam": true, 21 21 "uses-erlang-externals": false, 22 - "uses-javascript-externals": false 22 + "uses-javascript-externals": false, 23 + "can-run-on-erlang": true, 24 + "can-run-on-javascript": true 23 25 }, 24 26 "type": { 25 27 "kind": "named", ··· 35 37 "implementations": { 36 38 "gleam": true, 37 39 "uses-erlang-externals": false, 38 - "uses-javascript-externals": false 40 + "uses-javascript-externals": false, 41 + "can-run-on-erlang": true, 42 + "can-run-on-javascript": true 39 43 }, 40 44 "type": { 41 45 "kind": "named", ··· 51 55 "implementations": { 52 56 "gleam": true, 53 57 "uses-erlang-externals": false, 54 - "uses-javascript-externals": false 58 + "uses-javascript-externals": false, 59 + "can-run-on-erlang": true, 60 + "can-run-on-javascript": true 55 61 }, 56 62 "type": { 57 63 "kind": "named", ··· 67 73 "implementations": { 68 74 "gleam": true, 69 75 "uses-erlang-externals": false, 70 - "uses-javascript-externals": false 76 + "uses-javascript-externals": false, 77 + "can-run-on-erlang": true, 78 + "can-run-on-javascript": true 71 79 }, 72 80 "type": { 73 81 "kind": "named",
+4
compiler-core/src/parse.rs
··· 1618 1618 external_javascript: attributes.external_javascript.take(), 1619 1619 implementations: Implementations { 1620 1620 gleam: true, 1621 + can_run_on_erlang: true, 1622 + can_run_on_javascript: true, 1621 1623 uses_erlang_externals: false, 1622 1624 uses_javascript_externals: false, 1623 1625 }, ··· 2255 2257 deprecation: attributes.deprecated.clone(), 2256 2258 implementations: Implementations { 2257 2259 gleam: true, 2260 + can_run_on_erlang: true, 2261 + can_run_on_javascript: true, 2258 2262 uses_erlang_externals: false, 2259 2263 uses_javascript_externals: false, 2260 2264 },
+2
compiler-core/src/type_.rs
··· 462 462 | ValueConstructorVariant::LocalConstant { .. } 463 463 | ValueConstructorVariant::LocalVariable { .. } => Implementations { 464 464 gleam: true, 465 + can_run_on_erlang: true, 466 + can_run_on_javascript: true, 465 467 uses_javascript_externals: false, 466 468 uses_erlang_externals: false, 467 469 },
+41 -17
compiler-core/src/type_/expression.rs
··· 36 36 /// is added - say a WASM target - `func` wouldn't support it! On the other 37 37 /// hand, a pure Gleam function will support all future targets. 38 38 pub gleam: bool, 39 + pub can_run_on_erlang: bool, 40 + pub can_run_on_javascript: bool, 39 41 /// Wether the function has an implementation that uses external erlang 40 42 /// code. 41 43 pub uses_erlang_externals: bool, ··· 49 51 /// This is used to determine whether an error should be raised in the case when 50 52 /// a value is used that does not have an implementation for the current target. 51 53 #[derive(Clone, Copy, Debug)] 52 - pub struct Externals { 54 + pub struct FunctionDefinition { 55 + /// The function has { ... } after the function head 56 + pub has_body: bool, 53 57 /// The function has @external(erlang, "...", "...") 54 - pub erlang: bool, 58 + pub has_erlang_external: bool, 55 59 /// The function has @external(JavaScript, "...", "...") 56 - pub javascript: bool, 60 + pub has_javascript_external: bool, 57 61 } 58 62 59 - impl Externals { 63 + impl FunctionDefinition { 60 64 pub fn exists(&self, target: Target) -> bool { 61 65 match target { 62 - Target::Erlang => self.erlang, 63 - Target::JavaScript => self.javascript, 66 + Target::Erlang => self.has_erlang_external, 67 + Target::JavaScript => self.has_javascript_external, 64 68 } 65 69 } 66 70 } ··· 69 73 /// Given the implementations of a function update those with taking into 70 74 /// account the `implementations` of another function (or constant) used 71 75 /// inside its body. 72 - pub fn update_from_use(&mut self, implementations: &Implementations) { 76 + pub fn update_from_use( 77 + &mut self, 78 + implementations: &Implementations, 79 + current_function_definition: &FunctionDefinition, 80 + ) { 73 81 // With this pattern matching we won't forget to deal with new targets 74 82 // when those are added :) 75 83 let Implementations { 76 84 gleam, 77 85 uses_erlang_externals, 78 86 uses_javascript_externals, 87 + can_run_on_erlang, 88 + can_run_on_javascript, 79 89 } = implementations; 90 + let FunctionDefinition { 91 + has_body: _, 92 + has_erlang_external, 93 + has_javascript_external, 94 + } = current_function_definition; 80 95 81 96 // If a pure-Gleam function uses a function that doesn't have a pure 82 97 // Gleam implementation, then it's no longer pure-Gleam. 83 98 self.gleam = self.gleam && *gleam; 99 + 100 + // A function can run on a target if the code that it uses can run on on 101 + // the same target, 102 + self.can_run_on_erlang = 103 + *has_erlang_external || (self.can_run_on_erlang && (*gleam || *can_run_on_erlang)); 104 + self.can_run_on_javascript = *has_javascript_external 105 + || (self.can_run_on_javascript && (*gleam || *can_run_on_javascript)); 84 106 85 107 // If a function uses a function that relies on external code (be it 86 108 // javascript or erlang) then it's considered as using external code as ··· 112 134 pub fn supports(&self, target: Target) -> bool { 113 135 self.gleam 114 136 || match target { 115 - Target::Erlang => self.uses_erlang_externals, 116 - Target::JavaScript => self.uses_javascript_externals, 137 + Target::Erlang => self.can_run_on_erlang, 138 + Target::JavaScript => self.can_run_on_javascript, 117 139 } 118 140 } 119 141 } ··· 123 145 pub(crate) environment: &'a mut Environment<'b>, 124 146 125 147 pub(crate) implementations: Implementations, 126 - pub(crate) current_function_externals: Externals, 148 + pub(crate) current_function_definition: FunctionDefinition, 127 149 128 150 // Type hydrator for creating types from annotations 129 151 pub(crate) hydrator: Hydrator, 130 152 } 131 153 132 154 impl<'a, 'b> ExprTyper<'a, 'b> { 133 - pub fn new(environment: &'a mut Environment<'b>, externals: Externals) -> Self { 155 + pub fn new(environment: &'a mut Environment<'b>, definition: FunctionDefinition) -> Self { 134 156 let mut hydrator = Hydrator::new(); 135 157 136 158 let implementations = Implementations { 137 159 // We start assuming the function is pure Gleam and narrow it down 138 160 // if we run into functions/constants that have only external 139 161 // implementations for some of the targets. 140 - gleam: true, 141 - uses_erlang_externals: externals.erlang, 142 - uses_javascript_externals: externals.javascript, 162 + gleam: definition.has_body, 163 + can_run_on_erlang: definition.has_body || definition.has_erlang_external, 164 + can_run_on_javascript: definition.has_body || definition.has_javascript_external, 165 + uses_erlang_externals: definition.has_erlang_external, 166 + uses_javascript_externals: definition.has_javascript_external, 143 167 }; 144 168 145 169 hydrator.permit_holes(true); ··· 147 171 hydrator, 148 172 environment, 149 173 implementations, 150 - current_function_externals: externals, 174 + current_function_definition: definition, 151 175 } 152 176 } 153 177 ··· 714 738 }; 715 739 716 740 self.implementations 717 - .update_from_use(variant_implementations); 741 + .update_from_use(variant_implementations, &self.current_function_definition); 718 742 719 743 if self.environment.target_support.is_enforced() 720 744 // If the value used doesn't have an implementation that can be used ··· 722 746 && !variant_implementations.supports(self.environment.target) 723 747 // ... and there is not an external implementation for it 724 748 && !self 725 - .current_function_externals 749 + .current_function_definition 726 750 .exists(self.environment.target) 727 751 { 728 752 Err(Error::UnsupportedExpressionTarget {
+17 -6
compiler-core/src/type_/tests.rs
··· 4 4 ast::{TypedModule, TypedStatement, UntypedExpr, UntypedModule}, 5 5 build::{Origin, Target}, 6 6 error::Error, 7 - type_::{build_prelude, expression::Externals, pretty::Printer}, 7 + type_::{build_prelude, expression::FunctionDefinition, pretty::Printer}, 8 8 uid::UniqueIdGenerator, 9 9 warning::{TypeWarningEmitter, VectorWarningEmitterIO, WarningEmitter, WarningEmitterIO}, 10 10 }; ··· 267 267 &TypeWarningEmitter::null(), 268 268 TargetSupport::Enforced, 269 269 ), 270 - Externals { 271 - erlang: false, 272 - javascript: false, 270 + FunctionDefinition { 271 + has_body: true, 272 + has_erlang_external: false, 273 + has_javascript_external: false, 273 274 }, 274 275 ) 275 276 .infer_statements(ast) ··· 2012 2013 gleam: true, 2013 2014 uses_erlang_externals: false, 2014 2015 uses_javascript_externals: false, 2016 + can_run_on_erlang: true, 2017 + can_run_on_javascript: true, 2015 2018 }, 2016 2019 }, 2017 2020 }; ··· 2035 2038 gleam: true, 2036 2039 uses_erlang_externals: false, 2037 2040 uses_javascript_externals: false, 2041 + can_run_on_erlang: true, 2042 + can_run_on_javascript: true, 2038 2043 }, 2039 2044 }, 2040 2045 }; ··· 2058 2063 gleam: true, 2059 2064 uses_erlang_externals: false, 2060 2065 uses_javascript_externals: false, 2066 + can_run_on_erlang: true, 2067 + can_run_on_javascript: true, 2061 2068 }, 2062 2069 }, 2063 2070 }; ··· 2079 2086 module: "module".into(), 2080 2087 implementations: Implementations { 2081 2088 gleam: false, 2082 - uses_erlang_externals: false, 2089 + uses_erlang_externals: true, 2083 2090 uses_javascript_externals: true, 2091 + can_run_on_erlang: false, 2092 + can_run_on_javascript: true, 2084 2093 }, 2085 2094 }, 2086 2095 }; ··· 2103 2112 implementations: Implementations { 2104 2113 gleam: false, 2105 2114 uses_erlang_externals: true, 2106 - uses_javascript_externals: false, 2115 + uses_javascript_externals: true, 2116 + can_run_on_erlang: true, 2117 + can_run_on_javascript: false, 2107 2118 }, 2108 2119 }, 2109 2120 };
+35 -5
compiler-core/src/type_/tests/target_implementations.rs
··· 49 49 gleam: true, 50 50 uses_erlang_externals: false, 51 51 uses_javascript_externals: false, 52 + can_run_on_erlang: true, 53 + can_run_on_javascript: true, 52 54 } 53 55 ), 54 56 ( ··· 57 59 gleam: true, 58 60 uses_erlang_externals: false, 59 61 uses_javascript_externals: false, 62 + can_run_on_erlang: true, 63 + can_run_on_javascript: true, 60 64 } 61 65 ) 62 66 ], ··· 79 83 gleam: false, 80 84 uses_erlang_externals: true, 81 85 uses_javascript_externals: false, 86 + can_run_on_erlang: true, 87 + can_run_on_javascript: false, 82 88 } 83 89 ), 84 90 ( ··· 87 93 gleam: false, 88 94 uses_erlang_externals: true, 89 95 uses_javascript_externals: false, 96 + can_run_on_erlang: true, 97 + can_run_on_javascript: false, 90 98 } 91 99 ) 92 100 ], ··· 110 118 gleam: false, 111 119 uses_erlang_externals: true, 112 120 uses_javascript_externals: true, 121 + can_run_on_erlang: true, 122 + can_run_on_javascript: true, 113 123 } 114 124 ), 115 125 ( ··· 118 128 gleam: false, 119 129 uses_erlang_externals: true, 120 130 uses_javascript_externals: true, 131 + can_run_on_erlang: true, 132 + can_run_on_javascript: true, 121 133 } 122 134 ) 123 135 ], ··· 145 157 gleam: true, 146 158 uses_erlang_externals: true, 147 159 uses_javascript_externals: false, 160 + can_run_on_erlang: true, 161 + can_run_on_javascript: true, 148 162 } 149 163 ), 150 164 ( ··· 153 167 gleam: true, 154 168 uses_erlang_externals: false, 155 169 uses_javascript_externals: true, 170 + can_run_on_erlang: true, 171 + can_run_on_javascript: true, 156 172 } 157 173 ), 158 174 ( ··· 161 177 gleam: true, 162 178 uses_erlang_externals: true, 163 179 uses_javascript_externals: true, 180 + can_run_on_erlang: true, 181 + can_run_on_javascript: true, 164 182 } 165 183 ) 166 184 ], ··· 186 204 gleam: false, 187 205 uses_erlang_externals: true, 188 206 uses_javascript_externals: true, 207 + can_run_on_erlang: true, 208 + can_run_on_javascript: true, 189 209 } 190 210 ), 191 211 ( ··· 194 214 gleam: false, 195 215 uses_erlang_externals: true, 196 216 uses_javascript_externals: true, 217 + can_run_on_erlang: true, 218 + can_run_on_javascript: true, 197 219 } 198 220 ), 199 221 ( ··· 202 224 gleam: false, 203 225 uses_erlang_externals: false, 204 226 uses_javascript_externals: true, 227 + can_run_on_erlang: false, 228 + can_run_on_javascript: true, 205 229 } 206 230 ) 207 231 ], ··· 227 251 gleam: false, 228 252 uses_erlang_externals: true, 229 253 uses_javascript_externals: true, 254 + can_run_on_erlang: true, 255 + can_run_on_javascript: true, 230 256 } 231 257 ), 232 258 ( ··· 235 261 gleam: false, 236 262 uses_erlang_externals: true, 237 263 uses_javascript_externals: false, 264 + can_run_on_erlang: true, 265 + can_run_on_javascript: false, 238 266 } 239 267 ), 240 268 ( ··· 243 271 gleam: false, 244 272 uses_erlang_externals: true, 245 273 uses_javascript_externals: true, 274 + can_run_on_erlang: true, 275 + can_run_on_javascript: true, 246 276 } 247 277 ) 248 278 ], ··· 255 285 r#" 256 286 @external(javascript, "foo", "bar") 257 287 fn javascript_only() -> Int 258 - 288 + 259 289 @external(erlang, "foo", "bar") 260 290 fn erlang_only() -> Int 261 291 ··· 273 303 @external(erlang, "foo", "bar") 274 304 @external(javascript, "foo", "bar") 275 305 fn both_external() -> Int 276 - 306 + 277 307 @external(javascript, "foo", "bar") 278 308 fn javascript_only() -> Int 279 309 ··· 293 323 @external(erlang, "foo", "bar") 294 324 @external(javascript, "foo", "bar") 295 325 fn both_external() -> Int 296 - 326 + 297 327 @external(erlang, "foo", "bar") 298 328 fn erlang_only() -> Int 299 329 ··· 318 348 @external(erlang, "foo", "bar") 319 349 @external(javascript, "foo", "bar") 320 350 fn both_external() -> Int 321 - 351 + 322 352 @external(javascript, "foo", "bar") 323 353 fn javascript_only() -> Int 324 354 ··· 338 368 @external(erlang, "foo", "bar") 339 369 @external(javascript, "foo", "bar") 340 370 fn both_external() -> Int 341 - 371 + 342 372 @external(erlang, "foo", "bar") 343 373 fn erlang_only() -> Int 344 374