feat: add prelude
This commit is contained in:
parent
4df3de0a03
commit
d0287d418b
|
@ -4,7 +4,7 @@ use std::{
|
|||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use aiken_lang::{ast::ModuleKind, builtins, tipo};
|
||||
use aiken_lang::{ast::ModuleKind, builtins, tipo, IdGenerator};
|
||||
|
||||
use crate::{
|
||||
config::Config,
|
||||
|
@ -38,6 +38,7 @@ impl Warning {
|
|||
pub struct Project {
|
||||
config: Config,
|
||||
defined_modules: HashMap<String, PathBuf>,
|
||||
id_gen: IdGenerator,
|
||||
module_types: HashMap<String, tipo::Module>,
|
||||
root: PathBuf,
|
||||
sources: Vec<Source>,
|
||||
|
@ -46,13 +47,16 @@ pub struct Project {
|
|||
|
||||
impl Project {
|
||||
pub fn new(config: Config, root: PathBuf) -> Project {
|
||||
let id_gen = IdGenerator::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 {
|
||||
config,
|
||||
defined_modules: HashMap::new(),
|
||||
id_gen,
|
||||
module_types,
|
||||
root,
|
||||
sources: vec![],
|
||||
|
@ -161,6 +165,7 @@ impl Project {
|
|||
let mut type_warnings = Vec::new();
|
||||
|
||||
let ast = tipo::infer::module(
|
||||
&self.id_gen,
|
||||
ast,
|
||||
kind,
|
||||
&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 {
|
||||
name: vec!["gleam".to_string()],
|
||||
name: vec!["aiken".to_string()],
|
||||
package: "".to_string(),
|
||||
kind: ModuleKind::Lib,
|
||||
types: HashMap::new(),
|
||||
|
@ -13,5 +27,255 @@ pub fn prelude() -> tipo::Module {
|
|||
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
|
||||
}
|
||||
|
||||
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 builtins;
|
||||
pub mod error;
|
||||
|
@ -7,5 +9,20 @@ pub mod parser;
|
|||
pub mod tipo;
|
||||
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)]
|
||||
mod tests;
|
||||
|
|
|
@ -26,7 +26,7 @@ pub enum Type {
|
|||
///
|
||||
Fn {
|
||||
args: Vec<Arc<Type>>,
|
||||
retrn: Arc<Type>,
|
||||
ret: Arc<Type>,
|
||||
},
|
||||
|
||||
/// A type variable. See the contained `TypeVar` enum for more information.
|
||||
|
@ -74,6 +74,16 @@ pub struct ValueConstructor {
|
|||
pub tipo: Arc<Type>,
|
||||
}
|
||||
|
||||
impl ValueConstructor {
|
||||
pub fn public(tipo: Arc<Type>, variant: ValueConstructorVariant) -> ValueConstructor {
|
||||
ValueConstructor {
|
||||
public: true,
|
||||
variant,
|
||||
tipo,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum ValueConstructorVariant {
|
||||
/// A locally defined variable or function parameter
|
||||
|
@ -102,6 +112,7 @@ pub enum ValueConstructorVariant {
|
|||
field_map: Option<FieldMap>,
|
||||
location: Span,
|
||||
module: String,
|
||||
constructors_count: u16,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -122,7 +133,7 @@ pub struct TypeConstructor {
|
|||
pub origin: Span,
|
||||
pub module: Vec<String>,
|
||||
pub parameters: Vec<Arc<Type>>,
|
||||
pub typ: Arc<Type>,
|
||||
pub tipo: Arc<Type>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use crate::ast::{ModuleKind, TypedModule, UntypedModule};
|
||||
use crate::{
|
||||
ast::{ModuleKind, TypedModule, UntypedModule},
|
||||
IdGenerator,
|
||||
};
|
||||
|
||||
use super::{
|
||||
error::{Error, Warning},
|
||||
|
@ -8,7 +11,7 @@ use super::{
|
|||
};
|
||||
|
||||
pub fn module(
|
||||
// ids: &UniqueIdGenerator,
|
||||
id_gen: &IdGenerator,
|
||||
mut module: UntypedModule,
|
||||
kind: ModuleKind,
|
||||
package: &str,
|
||||
|
|
Loading…
Reference in New Issue