Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 78879ca94e | |||
| 01474b401f | |||
| 169de0b3c8 | |||
| 667a94b4dc | |||
| 1b629aaae4 |
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -776,7 +776,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lux"
|
name = "lux"
|
||||||
version = "0.1.8"
|
version = "0.1.9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glob",
|
"glob",
|
||||||
"lsp-server",
|
"lsp-server",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lux"
|
name = "lux"
|
||||||
version = "0.1.9"
|
version = "0.1.11"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "A functional programming language with first-class effects, schema evolution, and behavioral types"
|
description = "A functional programming language with first-class effects, schema evolution, and behavioral types"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
printf "\n"
|
printf "\n"
|
||||||
printf " \033[1;35m╦ ╦ ╦╦ ╦\033[0m\n"
|
printf " \033[1;35m╦ ╦ ╦╦ ╦\033[0m\n"
|
||||||
printf " \033[1;35m║ ║ ║╔╣\033[0m\n"
|
printf " \033[1;35m║ ║ ║╔╣\033[0m\n"
|
||||||
printf " \033[1;35m╩═╝╚═╝╩ ╩\033[0m v0.1.9\n"
|
printf " \033[1;35m╩═╝╚═╝╩ ╩\033[0m v0.1.11\n"
|
||||||
printf "\n"
|
printf "\n"
|
||||||
printf " Functional language with first-class effects\n"
|
printf " Functional language with first-class effects\n"
|
||||||
printf "\n"
|
printf "\n"
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
|
|
||||||
packages.default = pkgs.rustPlatform.buildRustPackage {
|
packages.default = pkgs.rustPlatform.buildRustPackage {
|
||||||
pname = "lux";
|
pname = "lux";
|
||||||
version = "0.1.9";
|
version = "0.1.11";
|
||||||
src = ./.;
|
src = ./.;
|
||||||
cargoLock.lockFile = ./Cargo.lock;
|
cargoLock.lockFile = ./Cargo.lock;
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
};
|
};
|
||||||
in muslPkgs.rustPlatform.buildRustPackage {
|
in muslPkgs.rustPlatform.buildRustPackage {
|
||||||
pname = "lux";
|
pname = "lux";
|
||||||
version = "0.1.9";
|
version = "0.1.11";
|
||||||
src = ./.;
|
src = ./.;
|
||||||
cargoLock.lockFile = ./Cargo.lock;
|
cargoLock.lockFile = ./Cargo.lock;
|
||||||
|
|
||||||
|
|||||||
15
src/ast.rs
15
src/ast.rs
@@ -223,6 +223,8 @@ pub enum Declaration {
|
|||||||
Impl(ImplDecl),
|
Impl(ImplDecl),
|
||||||
/// Extern function declaration (FFI): extern fn name(params): ReturnType
|
/// Extern function declaration (FFI): extern fn name(params): ReturnType
|
||||||
ExternFn(ExternFnDecl),
|
ExternFn(ExternFnDecl),
|
||||||
|
/// Extern let declaration (FFI): extern let name: Type
|
||||||
|
ExternLet(ExternLetDecl),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Function declaration
|
/// Function declaration
|
||||||
@@ -445,6 +447,19 @@ pub struct ExternFnDecl {
|
|||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extern let declaration (FFI)
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ExternLetDecl {
|
||||||
|
pub visibility: Visibility,
|
||||||
|
/// Documentation comment
|
||||||
|
pub doc: Option<String>,
|
||||||
|
pub name: Ident,
|
||||||
|
pub typ: TypeExpr,
|
||||||
|
/// Optional JS name override: extern let foo: T = "window.foo"
|
||||||
|
pub js_name: Option<String>,
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
/// Type expressions
|
/// Type expressions
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum TypeExpr {
|
pub enum TypeExpr {
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ pub struct JsBackend {
|
|||||||
used_effects: HashSet<String>,
|
used_effects: HashSet<String>,
|
||||||
/// Extern function names mapped to their JS names
|
/// Extern function names mapped to their JS names
|
||||||
extern_fns: HashMap<String, String>,
|
extern_fns: HashMap<String, String>,
|
||||||
|
/// Extern let names mapped to their JS names
|
||||||
|
extern_lets: HashMap<String, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JsBackend {
|
impl JsBackend {
|
||||||
@@ -96,6 +98,7 @@ impl JsBackend {
|
|||||||
var_substitutions: HashMap::new(),
|
var_substitutions: HashMap::new(),
|
||||||
used_effects: HashSet::new(),
|
used_effects: HashSet::new(),
|
||||||
extern_fns: HashMap::new(),
|
extern_fns: HashMap::new(),
|
||||||
|
extern_lets: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,6 +126,13 @@ impl JsBackend {
|
|||||||
self.extern_fns.insert(ext.name.name.clone(), js_name);
|
self.extern_fns.insert(ext.name.name.clone(), js_name);
|
||||||
self.functions.insert(ext.name.name.clone());
|
self.functions.insert(ext.name.name.clone());
|
||||||
}
|
}
|
||||||
|
Declaration::ExternLet(ext) => {
|
||||||
|
let js_name = ext
|
||||||
|
.js_name
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(|| ext.name.name.clone());
|
||||||
|
self.extern_lets.insert(ext.name.name.clone(), js_name);
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1097,6 +1107,9 @@ impl JsBackend {
|
|||||||
} else if self.functions.contains(&ident.name) {
|
} else if self.functions.contains(&ident.name) {
|
||||||
// Function reference (used as value)
|
// Function reference (used as value)
|
||||||
Ok(self.mangle_name(&ident.name))
|
Ok(self.mangle_name(&ident.name))
|
||||||
|
} else if let Some(js_name) = self.extern_lets.get(&ident.name) {
|
||||||
|
// Extern let: use JS name directly (no mangling)
|
||||||
|
Ok(js_name.clone())
|
||||||
} else {
|
} else {
|
||||||
Ok(self.escape_js_keyword(&ident.name))
|
Ok(self.escape_js_keyword(&ident.name))
|
||||||
}
|
}
|
||||||
@@ -1835,6 +1848,67 @@ impl JsBackend {
|
|||||||
let func = self.emit_expr(&args[1])?;
|
let func = self.emit_expr(&args[1])?;
|
||||||
Ok(format!("[...{}].sort({})", list, func))
|
Ok(format!("[...{}].sort({})", list, func))
|
||||||
}
|
}
|
||||||
|
"find" => {
|
||||||
|
let list = self.emit_expr(&args[0])?;
|
||||||
|
let pred = self.emit_expr(&args[1])?;
|
||||||
|
Ok(format!(
|
||||||
|
"((__l) => {{ const __r = __l.find({}); return __r !== undefined ? Lux.Some(__r) : Lux.None(); }})({})",
|
||||||
|
pred, list
|
||||||
|
))
|
||||||
|
}
|
||||||
|
"findIndex" => {
|
||||||
|
let list = self.emit_expr(&args[0])?;
|
||||||
|
let pred = self.emit_expr(&args[1])?;
|
||||||
|
Ok(format!(
|
||||||
|
"((__l) => {{ const __i = __l.findIndex({}); return __i !== -1 ? Lux.Some(__i) : Lux.None(); }})({})",
|
||||||
|
pred, list
|
||||||
|
))
|
||||||
|
}
|
||||||
|
"any" => {
|
||||||
|
let list = self.emit_expr(&args[0])?;
|
||||||
|
let pred = self.emit_expr(&args[1])?;
|
||||||
|
Ok(format!("{}.some({})", list, pred))
|
||||||
|
}
|
||||||
|
"all" => {
|
||||||
|
let list = self.emit_expr(&args[0])?;
|
||||||
|
let pred = self.emit_expr(&args[1])?;
|
||||||
|
Ok(format!("{}.every({})", list, pred))
|
||||||
|
}
|
||||||
|
"zip" => {
|
||||||
|
let list1 = self.emit_expr(&args[0])?;
|
||||||
|
let list2 = self.emit_expr(&args[1])?;
|
||||||
|
Ok(format!(
|
||||||
|
"((__a, __b) => __a.slice(0, Math.min(__a.length, __b.length)).map((__x, __i) => [__x, __b[__i]]))({})",
|
||||||
|
format!("{}, {}", list1, list2)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
"flatten" => {
|
||||||
|
let list = self.emit_expr(&args[0])?;
|
||||||
|
Ok(format!("{}.flat()", list))
|
||||||
|
}
|
||||||
|
"contains" => {
|
||||||
|
let list = self.emit_expr(&args[0])?;
|
||||||
|
let elem = self.emit_expr(&args[1])?;
|
||||||
|
Ok(format!(
|
||||||
|
"{}.some(__x => JSON.stringify(__x) === JSON.stringify({}))",
|
||||||
|
list, elem
|
||||||
|
))
|
||||||
|
}
|
||||||
|
"take" => {
|
||||||
|
let list = self.emit_expr(&args[0])?;
|
||||||
|
let n = self.emit_expr(&args[1])?;
|
||||||
|
Ok(format!("{}.slice(0, Math.max(0, {}))", list, n))
|
||||||
|
}
|
||||||
|
"drop" => {
|
||||||
|
let list = self.emit_expr(&args[0])?;
|
||||||
|
let n = self.emit_expr(&args[1])?;
|
||||||
|
Ok(format!("{}.slice(Math.max(0, {}))", list, n))
|
||||||
|
}
|
||||||
|
"forEach" => {
|
||||||
|
let list = self.emit_expr(&args[0])?;
|
||||||
|
let func = self.emit_expr(&args[1])?;
|
||||||
|
Ok(format!("({}.forEach({}), undefined)", list, func))
|
||||||
|
}
|
||||||
_ => Err(JsGenError {
|
_ => Err(JsGenError {
|
||||||
message: format!("Unknown List operation: {}", operation),
|
message: format!("Unknown List operation: {}", operation),
|
||||||
span: None,
|
span: None,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//! Formats Lux source code according to standard style guidelines.
|
//! Formats Lux source code according to standard style guidelines.
|
||||||
|
|
||||||
use crate::ast::{
|
use crate::ast::{
|
||||||
BehavioralProperty, BinaryOp, Declaration, EffectDecl, ExternFnDecl, Expr, FunctionDecl,
|
BehavioralProperty, BinaryOp, Declaration, EffectDecl, ExternFnDecl, ExternLetDecl, Expr, FunctionDecl,
|
||||||
HandlerDecl, ImplDecl, ImplMethod, LetDecl, Literal, LiteralKind, Pattern, Program, Statement,
|
HandlerDecl, ImplDecl, ImplMethod, LetDecl, Literal, LiteralKind, Pattern, Program, Statement,
|
||||||
TraitDecl, TypeDecl, TypeDef, TypeExpr, UnaryOp, VariantFields, Visibility,
|
TraitDecl, TypeDecl, TypeDef, TypeExpr, UnaryOp, VariantFields, Visibility,
|
||||||
};
|
};
|
||||||
@@ -104,6 +104,7 @@ impl Formatter {
|
|||||||
Declaration::Trait(t) => self.format_trait(t),
|
Declaration::Trait(t) => self.format_trait(t),
|
||||||
Declaration::Impl(i) => self.format_impl(i),
|
Declaration::Impl(i) => self.format_impl(i),
|
||||||
Declaration::ExternFn(e) => self.format_extern_fn(e),
|
Declaration::ExternFn(e) => self.format_extern_fn(e),
|
||||||
|
Declaration::ExternLet(e) => self.format_extern_let(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,6 +153,27 @@ impl Formatter {
|
|||||||
self.newline();
|
self.newline();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn format_extern_let(&mut self, ext: &ExternLetDecl) {
|
||||||
|
let indent = self.indent();
|
||||||
|
self.write(&indent);
|
||||||
|
|
||||||
|
if ext.visibility == Visibility::Public {
|
||||||
|
self.write("pub ");
|
||||||
|
}
|
||||||
|
|
||||||
|
self.write("extern let ");
|
||||||
|
self.write(&ext.name.name);
|
||||||
|
self.write(": ");
|
||||||
|
self.write(&self.format_type_expr(&ext.typ));
|
||||||
|
|
||||||
|
// Optional JS name
|
||||||
|
if let Some(js_name) = &ext.js_name {
|
||||||
|
self.write(&format!(" = \"{}\"", js_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.newline();
|
||||||
|
}
|
||||||
|
|
||||||
fn format_function(&mut self, func: &FunctionDecl) {
|
fn format_function(&mut self, func: &FunctionDecl) {
|
||||||
let indent = self.indent();
|
let indent = self.indent();
|
||||||
self.write(&indent);
|
self.write(&indent);
|
||||||
|
|||||||
@@ -1431,6 +1431,14 @@ impl Interpreter {
|
|||||||
Ok(Value::Unit)
|
Ok(Value::Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Declaration::ExternLet(ext) => {
|
||||||
|
// Register a placeholder that errors at runtime (extern lets only work in JS)
|
||||||
|
let name = ext.name.name.clone();
|
||||||
|
self.global_env
|
||||||
|
.define(&name, Value::ExternFn { name: name.clone(), arity: 0 });
|
||||||
|
Ok(Value::Unit)
|
||||||
|
}
|
||||||
|
|
||||||
Declaration::Effect(_) | Declaration::Trait(_) | Declaration::Impl(_) => {
|
Declaration::Effect(_) | Declaration::Trait(_) | Declaration::Impl(_) => {
|
||||||
// These are compile-time only
|
// These are compile-time only
|
||||||
Ok(Value::Unit)
|
Ok(Value::Unit)
|
||||||
|
|||||||
@@ -406,6 +406,9 @@ impl Linter {
|
|||||||
Declaration::ExternFn(e) => {
|
Declaration::ExternFn(e) => {
|
||||||
self.defined_functions.insert(e.name.name.clone());
|
self.defined_functions.insert(e.name.name.clone());
|
||||||
}
|
}
|
||||||
|
Declaration::ExternLet(e) => {
|
||||||
|
self.define_var(&e.name.name);
|
||||||
|
}
|
||||||
Declaration::Let(l) => {
|
Declaration::Let(l) => {
|
||||||
self.define_var(&l.name.name);
|
self.define_var(&l.name.name);
|
||||||
}
|
}
|
||||||
|
|||||||
19
src/main.rs
19
src/main.rs
@@ -2311,6 +2311,25 @@ fn extract_module_doc(source: &str, path: &str) -> Result<ModuleDoc, String> {
|
|||||||
properties: vec![],
|
properties: vec![],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
ast::Declaration::ExternLet(ext) => {
|
||||||
|
let js_note = ext.js_name.as_ref()
|
||||||
|
.map(|n| format!(" = \"{}\"", n))
|
||||||
|
.unwrap_or_default();
|
||||||
|
let signature = format!(
|
||||||
|
"extern let {}: {}{}",
|
||||||
|
ext.name.name,
|
||||||
|
format_type(&ext.typ),
|
||||||
|
js_note
|
||||||
|
);
|
||||||
|
let doc = extract_doc_comment(source, ext.span.start);
|
||||||
|
functions.push(FunctionDoc {
|
||||||
|
name: ext.name.name.clone(),
|
||||||
|
signature,
|
||||||
|
description: doc,
|
||||||
|
is_public: matches!(ext.visibility, ast::Visibility::Public),
|
||||||
|
properties: vec![],
|
||||||
|
});
|
||||||
|
}
|
||||||
ast::Declaration::Effect(e) => {
|
ast::Declaration::Effect(e) => {
|
||||||
let doc = extract_doc_comment(source, e.span.start);
|
let doc = extract_doc_comment(source, e.span.start);
|
||||||
let ops: Vec<String> = e.operations.iter()
|
let ops: Vec<String> = e.operations.iter()
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ impl Module {
|
|||||||
Declaration::Type(t) => t.visibility == Visibility::Public,
|
Declaration::Type(t) => t.visibility == Visibility::Public,
|
||||||
Declaration::Trait(t) => t.visibility == Visibility::Public,
|
Declaration::Trait(t) => t.visibility == Visibility::Public,
|
||||||
Declaration::ExternFn(e) => e.visibility == Visibility::Public,
|
Declaration::ExternFn(e) => e.visibility == Visibility::Public,
|
||||||
|
Declaration::ExternLet(e) => e.visibility == Visibility::Public,
|
||||||
// Effects, handlers, and impls are always public for now
|
// Effects, handlers, and impls are always public for now
|
||||||
Declaration::Effect(_) | Declaration::Handler(_) | Declaration::Impl(_) => true,
|
Declaration::Effect(_) | Declaration::Handler(_) | Declaration::Impl(_) => true,
|
||||||
}
|
}
|
||||||
@@ -298,6 +299,9 @@ impl ModuleLoader {
|
|||||||
Declaration::ExternFn(e) if e.visibility == Visibility::Public => {
|
Declaration::ExternFn(e) if e.visibility == Visibility::Public => {
|
||||||
exports.insert(e.name.name.clone());
|
exports.insert(e.name.name.clone());
|
||||||
}
|
}
|
||||||
|
Declaration::ExternLet(e) if e.visibility == Visibility::Public => {
|
||||||
|
exports.insert(e.name.name.clone());
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ impl Parser {
|
|||||||
|
|
||||||
match self.peek_kind() {
|
match self.peek_kind() {
|
||||||
TokenKind::Fn => Ok(Declaration::Function(self.parse_function_decl(visibility, doc)?)),
|
TokenKind::Fn => Ok(Declaration::Function(self.parse_function_decl(visibility, doc)?)),
|
||||||
TokenKind::Extern => Ok(Declaration::ExternFn(self.parse_extern_fn_decl(visibility, doc)?)),
|
TokenKind::Extern => self.parse_extern_decl(visibility, doc),
|
||||||
TokenKind::Effect => Ok(Declaration::Effect(self.parse_effect_decl(doc)?)),
|
TokenKind::Effect => Ok(Declaration::Effect(self.parse_effect_decl(doc)?)),
|
||||||
TokenKind::Handler => Ok(Declaration::Handler(self.parse_handler_decl()?)),
|
TokenKind::Handler => Ok(Declaration::Handler(self.parse_handler_decl()?)),
|
||||||
TokenKind::Type => Ok(Declaration::Type(self.parse_type_decl(visibility, doc)?)),
|
TokenKind::Type => Ok(Declaration::Type(self.parse_type_decl(visibility, doc)?)),
|
||||||
@@ -324,6 +324,58 @@ impl Parser {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse extern declaration: dispatch to extern fn or extern let
|
||||||
|
fn parse_extern_decl(&mut self, visibility: Visibility, doc: Option<String>) -> Result<Declaration, ParseError> {
|
||||||
|
// Peek past 'extern' to see if it's 'fn' or 'let'
|
||||||
|
if self.pos + 1 < self.tokens.len() {
|
||||||
|
match &self.tokens[self.pos + 1].kind {
|
||||||
|
TokenKind::Fn => Ok(Declaration::ExternFn(self.parse_extern_fn_decl(visibility, doc)?)),
|
||||||
|
TokenKind::Let => Ok(Declaration::ExternLet(self.parse_extern_let_decl(visibility, doc)?)),
|
||||||
|
_ => Err(self.error("Expected 'fn' or 'let' after 'extern'")),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(self.error("Expected 'fn' or 'let' after 'extern'"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse extern let declaration: extern let name: Type = "jsName"
|
||||||
|
fn parse_extern_let_decl(&mut self, visibility: Visibility, doc: Option<String>) -> Result<ExternLetDecl, ParseError> {
|
||||||
|
let start = self.current_span();
|
||||||
|
self.expect(TokenKind::Extern)?;
|
||||||
|
self.expect(TokenKind::Let)?;
|
||||||
|
|
||||||
|
let name = self.parse_ident()?;
|
||||||
|
|
||||||
|
// Type annotation
|
||||||
|
self.expect(TokenKind::Colon)?;
|
||||||
|
let typ = self.parse_type()?;
|
||||||
|
|
||||||
|
// Optional JS name override: = "jsName"
|
||||||
|
let js_name = if self.check(TokenKind::Eq) {
|
||||||
|
self.advance();
|
||||||
|
match self.peek_kind() {
|
||||||
|
TokenKind::String(s) => {
|
||||||
|
let name = s.clone();
|
||||||
|
self.advance();
|
||||||
|
Some(name)
|
||||||
|
}
|
||||||
|
_ => return Err(self.error("Expected string literal for JS name in extern let")),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let span = start.merge(self.previous_span());
|
||||||
|
Ok(ExternLetDecl {
|
||||||
|
visibility,
|
||||||
|
doc,
|
||||||
|
name,
|
||||||
|
typ,
|
||||||
|
js_name,
|
||||||
|
span,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse extern function declaration: extern fn name<T>(params): ReturnType = "jsName"
|
/// Parse extern function declaration: extern fn name<T>(params): ReturnType = "jsName"
|
||||||
fn parse_extern_fn_decl(&mut self, visibility: Visibility, doc: Option<String>) -> Result<ExternFnDecl, ParseError> {
|
fn parse_extern_fn_decl(&mut self, visibility: Visibility, doc: Option<String>) -> Result<ExternFnDecl, ParseError> {
|
||||||
let start = self.current_span();
|
let start = self.current_span();
|
||||||
|
|||||||
@@ -269,6 +269,24 @@ impl SymbolTable {
|
|||||||
let id = self.add_symbol(scope_idx, symbol);
|
let id = self.add_symbol(scope_idx, symbol);
|
||||||
self.add_reference(id, ext.name.span, true, true);
|
self.add_reference(id, ext.name.span, true, true);
|
||||||
}
|
}
|
||||||
|
Declaration::ExternLet(ext) => {
|
||||||
|
let is_public = matches!(ext.visibility, Visibility::Public);
|
||||||
|
let sig = format!(
|
||||||
|
"extern let {}: {}",
|
||||||
|
ext.name.name,
|
||||||
|
self.type_expr_to_string(&ext.typ)
|
||||||
|
);
|
||||||
|
let mut symbol = self.new_symbol(
|
||||||
|
ext.name.name.clone(),
|
||||||
|
SymbolKind::Variable,
|
||||||
|
ext.span,
|
||||||
|
Some(sig),
|
||||||
|
is_public,
|
||||||
|
);
|
||||||
|
symbol.documentation = ext.doc.clone();
|
||||||
|
let id = self.add_symbol(scope_idx, symbol);
|
||||||
|
self.add_reference(id, ext.name.span, true, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1238,6 +1238,11 @@ impl TypeChecker {
|
|||||||
let fn_type = Type::function(param_types, return_type);
|
let fn_type = Type::function(param_types, return_type);
|
||||||
self.env.bind(&ext.name.name, TypeScheme::mono(fn_type));
|
self.env.bind(&ext.name.name, TypeScheme::mono(fn_type));
|
||||||
}
|
}
|
||||||
|
Declaration::ExternLet(ext) => {
|
||||||
|
// Register extern let with its declared type
|
||||||
|
let typ = self.resolve_type(&ext.typ);
|
||||||
|
self.env.bind(&ext.name.name, TypeScheme::mono(typ));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user