feat: add prelude

This commit is contained in:
rvcas 2022-10-17 17:14:36 -04:00 committed by Lucas
parent 4df3de0a03
commit d0287d418b
5 changed files with 310 additions and 10 deletions

View File

@ -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,

View File

@ -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 })
}

View File

@ -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;

View File

@ -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)]

View File

@ -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,