feat: add prelude
This commit is contained in:
parent
4df3de0a03
commit
d0287d418b
|
@ -4,7 +4,7 @@ use std::{
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
use aiken_lang::{ast::ModuleKind, builtins, tipo};
|
use aiken_lang::{ast::ModuleKind, builtins, tipo, IdGenerator};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::Config,
|
config::Config,
|
||||||
|
@ -38,6 +38,7 @@ impl Warning {
|
||||||
pub struct Project {
|
pub struct Project {
|
||||||
config: Config,
|
config: Config,
|
||||||
defined_modules: HashMap<String, PathBuf>,
|
defined_modules: HashMap<String, PathBuf>,
|
||||||
|
id_gen: IdGenerator,
|
||||||
module_types: HashMap<String, tipo::Module>,
|
module_types: HashMap<String, tipo::Module>,
|
||||||
root: PathBuf,
|
root: PathBuf,
|
||||||
sources: Vec<Source>,
|
sources: Vec<Source>,
|
||||||
|
@ -46,13 +47,16 @@ pub struct Project {
|
||||||
|
|
||||||
impl Project {
|
impl Project {
|
||||||
pub fn new(config: Config, root: PathBuf) -> Project {
|
pub fn new(config: Config, root: PathBuf) -> Project {
|
||||||
|
let id_gen = IdGenerator::new();
|
||||||
|
|
||||||
let mut module_types = HashMap::new();
|
let mut module_types = HashMap::new();
|
||||||
|
|
||||||
module_types.insert("aiken".to_string(), builtins::prelude());
|
module_types.insert("aiken".to_string(), builtins::prelude(&id_gen));
|
||||||
|
|
||||||
Project {
|
Project {
|
||||||
config,
|
config,
|
||||||
defined_modules: HashMap::new(),
|
defined_modules: HashMap::new(),
|
||||||
|
id_gen,
|
||||||
module_types,
|
module_types,
|
||||||
root,
|
root,
|
||||||
sources: vec![],
|
sources: vec![],
|
||||||
|
@ -161,6 +165,7 @@ impl Project {
|
||||||
let mut type_warnings = Vec::new();
|
let mut type_warnings = Vec::new();
|
||||||
|
|
||||||
let ast = tipo::infer::module(
|
let ast = tipo::infer::module(
|
||||||
|
&self.id_gen,
|
||||||
ast,
|
ast,
|
||||||
kind,
|
kind,
|
||||||
&self.config.name,
|
&self.config.name,
|
||||||
|
|
|
@ -1,10 +1,24 @@
|
||||||
use std::collections::HashMap;
|
use std::{cell::RefCell, collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
use crate::{ast::ModuleKind, tipo};
|
use crate::{
|
||||||
|
ast::{ModuleKind, Span},
|
||||||
|
tipo::{self, Type, TypeConstructor, TypeVar, ValueConstructor, ValueConstructorVariant},
|
||||||
|
IdGenerator,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn prelude() -> tipo::Module {
|
const BYTE_ARRAY: &str = "ByteArray";
|
||||||
|
const BOOL: &str = "Bool";
|
||||||
|
const INT: &str = "Int";
|
||||||
|
const LIST: &str = "List";
|
||||||
|
const NIL: &str = "Nil";
|
||||||
|
const RESULT: &str = "Result";
|
||||||
|
const STRING: &str = "String";
|
||||||
|
|
||||||
|
/// Build a prelude that can be injected
|
||||||
|
/// into a compiler pipeline
|
||||||
|
pub fn prelude(id_gen: &IdGenerator) -> tipo::Module {
|
||||||
let mut prelude = tipo::Module {
|
let mut prelude = tipo::Module {
|
||||||
name: vec!["gleam".to_string()],
|
name: vec!["aiken".to_string()],
|
||||||
package: "".to_string(),
|
package: "".to_string(),
|
||||||
kind: ModuleKind::Lib,
|
kind: ModuleKind::Lib,
|
||||||
types: HashMap::new(),
|
types: HashMap::new(),
|
||||||
|
@ -13,5 +27,255 @@ pub fn prelude() -> tipo::Module {
|
||||||
accessors: HashMap::new(),
|
accessors: HashMap::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Int
|
||||||
|
prelude.types.insert(
|
||||||
|
INT.to_string(),
|
||||||
|
TypeConstructor {
|
||||||
|
parameters: vec![],
|
||||||
|
tipo: int(),
|
||||||
|
origin: Span::empty(),
|
||||||
|
module: vec![],
|
||||||
|
public: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// ByteArray
|
||||||
|
prelude.types.insert(
|
||||||
|
BYTE_ARRAY.to_string(),
|
||||||
|
TypeConstructor {
|
||||||
|
origin: Span::empty(),
|
||||||
|
parameters: vec![],
|
||||||
|
tipo: byte_array(),
|
||||||
|
module: vec![],
|
||||||
|
public: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Bool
|
||||||
|
prelude.types_constructors.insert(
|
||||||
|
BOOL.to_string(),
|
||||||
|
vec!["True".to_string(), "False".to_string()],
|
||||||
|
);
|
||||||
|
|
||||||
|
prelude.values.insert(
|
||||||
|
"True".to_string(),
|
||||||
|
ValueConstructor::public(
|
||||||
|
bool(),
|
||||||
|
ValueConstructorVariant::Record {
|
||||||
|
module: "".into(),
|
||||||
|
name: "True".to_string(),
|
||||||
|
field_map: None,
|
||||||
|
arity: 0,
|
||||||
|
location: Span::empty(),
|
||||||
|
constructors_count: 2,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
prelude.values.insert(
|
||||||
|
"False".to_string(),
|
||||||
|
ValueConstructor::public(
|
||||||
|
bool(),
|
||||||
|
ValueConstructorVariant::Record {
|
||||||
|
module: "".into(),
|
||||||
|
name: "False".to_string(),
|
||||||
|
field_map: None,
|
||||||
|
arity: 0,
|
||||||
|
location: Span::empty(),
|
||||||
|
constructors_count: 2,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
prelude.types.insert(
|
||||||
|
BOOL.to_string(),
|
||||||
|
TypeConstructor {
|
||||||
|
origin: Span::empty(),
|
||||||
|
parameters: vec![],
|
||||||
|
tipo: bool(),
|
||||||
|
module: vec![],
|
||||||
|
public: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// List(a)
|
||||||
|
let list_parameter = generic_var(id_gen.next());
|
||||||
|
prelude.types.insert(
|
||||||
|
LIST.to_string(),
|
||||||
|
TypeConstructor {
|
||||||
|
origin: Span::empty(),
|
||||||
|
parameters: vec![list_parameter.clone()],
|
||||||
|
tipo: list(list_parameter),
|
||||||
|
module: vec![],
|
||||||
|
public: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// String
|
||||||
|
prelude.types.insert(
|
||||||
|
STRING.to_string(),
|
||||||
|
TypeConstructor {
|
||||||
|
origin: Span::empty(),
|
||||||
|
parameters: vec![],
|
||||||
|
tipo: string(),
|
||||||
|
module: vec![],
|
||||||
|
public: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Nil
|
||||||
|
prelude.values.insert(
|
||||||
|
NIL.to_string(),
|
||||||
|
ValueConstructor::public(
|
||||||
|
nil(),
|
||||||
|
ValueConstructorVariant::Record {
|
||||||
|
module: "".into(),
|
||||||
|
name: NIL.to_string(),
|
||||||
|
arity: 0,
|
||||||
|
field_map: None,
|
||||||
|
location: Span::empty(),
|
||||||
|
constructors_count: 1,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
prelude.types.insert(
|
||||||
|
NIL.to_string(),
|
||||||
|
TypeConstructor {
|
||||||
|
origin: Span::empty(),
|
||||||
|
parameters: vec![],
|
||||||
|
tipo: nil(),
|
||||||
|
module: vec![],
|
||||||
|
public: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Result(value, error)
|
||||||
|
let result_value = generic_var(id_gen.next());
|
||||||
|
let result_error = generic_var(id_gen.next());
|
||||||
|
|
||||||
|
prelude.types.insert(
|
||||||
|
RESULT.to_string(),
|
||||||
|
TypeConstructor {
|
||||||
|
origin: Span::empty(),
|
||||||
|
parameters: vec![result_value.clone(), result_error.clone()],
|
||||||
|
tipo: result(result_value, result_error),
|
||||||
|
module: vec![],
|
||||||
|
public: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
prelude.types_constructors.insert(
|
||||||
|
RESULT.to_string(),
|
||||||
|
vec!["Ok".to_string(), "Err".to_string()],
|
||||||
|
);
|
||||||
|
|
||||||
|
let ok = generic_var(id_gen.next());
|
||||||
|
let error = generic_var(id_gen.next());
|
||||||
|
let _ = prelude.values.insert(
|
||||||
|
"Ok".to_string(),
|
||||||
|
ValueConstructor::public(
|
||||||
|
function(vec![ok.clone()], result(ok, error)),
|
||||||
|
ValueConstructorVariant::Record {
|
||||||
|
module: "".into(),
|
||||||
|
name: "Ok".to_string(),
|
||||||
|
field_map: None,
|
||||||
|
arity: 1,
|
||||||
|
location: Span::empty(),
|
||||||
|
constructors_count: 2,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
let ok = generic_var(id_gen.next());
|
||||||
|
let error = generic_var(id_gen.next());
|
||||||
|
let _ = prelude.values.insert(
|
||||||
|
"Error".to_string(),
|
||||||
|
ValueConstructor::public(
|
||||||
|
function(vec![error.clone()], result(ok, error)),
|
||||||
|
ValueConstructorVariant::Record {
|
||||||
|
module: "".into(),
|
||||||
|
name: "Error".to_string(),
|
||||||
|
field_map: None,
|
||||||
|
arity: 1,
|
||||||
|
location: Span::empty(),
|
||||||
|
constructors_count: 2,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
prelude
|
prelude
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn int() -> Arc<Type> {
|
||||||
|
Arc::new(Type::App {
|
||||||
|
public: true,
|
||||||
|
name: INT.to_string(),
|
||||||
|
module: vec![],
|
||||||
|
args: vec![],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn byte_array() -> Arc<Type> {
|
||||||
|
Arc::new(Type::App {
|
||||||
|
args: vec![],
|
||||||
|
public: true,
|
||||||
|
name: BYTE_ARRAY.to_string(),
|
||||||
|
module: vec![],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bool() -> Arc<Type> {
|
||||||
|
Arc::new(Type::App {
|
||||||
|
args: vec![],
|
||||||
|
public: true,
|
||||||
|
name: BOOL.to_string(),
|
||||||
|
module: vec![],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn list(t: Arc<Type>) -> Arc<Type> {
|
||||||
|
Arc::new(Type::App {
|
||||||
|
public: true,
|
||||||
|
name: LIST.to_string(),
|
||||||
|
module: vec![],
|
||||||
|
args: vec![t],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn string() -> Arc<Type> {
|
||||||
|
Arc::new(Type::App {
|
||||||
|
args: vec![],
|
||||||
|
public: true,
|
||||||
|
name: STRING.to_string(),
|
||||||
|
module: vec![],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn nil() -> Arc<Type> {
|
||||||
|
Arc::new(Type::App {
|
||||||
|
args: vec![],
|
||||||
|
public: true,
|
||||||
|
name: NIL.to_string(),
|
||||||
|
module: vec![],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn result(a: Arc<Type>, e: Arc<Type>) -> Arc<Type> {
|
||||||
|
Arc::new(Type::App {
|
||||||
|
public: true,
|
||||||
|
name: RESULT.to_string(),
|
||||||
|
module: vec![],
|
||||||
|
args: vec![a, e],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn function(args: Vec<Arc<Type>>, ret: Arc<Type>) -> Arc<Type> {
|
||||||
|
Arc::new(Type::Fn { ret, args })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generic_var(id: u64) -> Arc<Type> {
|
||||||
|
let tipo = Arc::new(RefCell::new(TypeVar::Generic { id }));
|
||||||
|
|
||||||
|
Arc::new(Type::Var { tipo })
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::sync::atomic::{AtomicU64, Ordering};
|
||||||
|
|
||||||
pub mod ast;
|
pub mod ast;
|
||||||
pub mod builtins;
|
pub mod builtins;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
@ -7,5 +9,20 @@ pub mod parser;
|
||||||
pub mod tipo;
|
pub mod tipo;
|
||||||
pub mod token;
|
pub mod token;
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct IdGenerator {
|
||||||
|
id: AtomicU64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IdGenerator {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next(&self) -> u64 {
|
||||||
|
self.id.fetch_add(1, Ordering::Relaxed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
|
@ -26,7 +26,7 @@ pub enum Type {
|
||||||
///
|
///
|
||||||
Fn {
|
Fn {
|
||||||
args: Vec<Arc<Type>>,
|
args: Vec<Arc<Type>>,
|
||||||
retrn: Arc<Type>,
|
ret: Arc<Type>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// A type variable. See the contained `TypeVar` enum for more information.
|
/// A type variable. See the contained `TypeVar` enum for more information.
|
||||||
|
@ -74,6 +74,16 @@ pub struct ValueConstructor {
|
||||||
pub tipo: Arc<Type>,
|
pub tipo: Arc<Type>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ValueConstructor {
|
||||||
|
pub fn public(tipo: Arc<Type>, variant: ValueConstructorVariant) -> ValueConstructor {
|
||||||
|
ValueConstructor {
|
||||||
|
public: true,
|
||||||
|
variant,
|
||||||
|
tipo,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum ValueConstructorVariant {
|
pub enum ValueConstructorVariant {
|
||||||
/// A locally defined variable or function parameter
|
/// A locally defined variable or function parameter
|
||||||
|
@ -102,6 +112,7 @@ pub enum ValueConstructorVariant {
|
||||||
field_map: Option<FieldMap>,
|
field_map: Option<FieldMap>,
|
||||||
location: Span,
|
location: Span,
|
||||||
module: String,
|
module: String,
|
||||||
|
constructors_count: u16,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +133,7 @@ pub struct TypeConstructor {
|
||||||
pub origin: Span,
|
pub origin: Span,
|
||||||
pub module: Vec<String>,
|
pub module: Vec<String>,
|
||||||
pub parameters: Vec<Arc<Type>>,
|
pub parameters: Vec<Arc<Type>>,
|
||||||
pub typ: Arc<Type>,
|
pub tipo: Arc<Type>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::ast::{ModuleKind, TypedModule, UntypedModule};
|
use crate::{
|
||||||
|
ast::{ModuleKind, TypedModule, UntypedModule},
|
||||||
|
IdGenerator,
|
||||||
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
error::{Error, Warning},
|
error::{Error, Warning},
|
||||||
|
@ -8,7 +11,7 @@ use super::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn module(
|
pub fn module(
|
||||||
// ids: &UniqueIdGenerator,
|
id_gen: &IdGenerator,
|
||||||
mut module: UntypedModule,
|
mut module: UntypedModule,
|
||||||
kind: ModuleKind,
|
kind: ModuleKind,
|
||||||
package: &str,
|
package: &str,
|
||||||
|
|
Loading…
Reference in New Issue