Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 21 additions & 22 deletions coal-core/src/ast/builtin.rs
Original file line number Diff line number Diff line change
@@ -1,48 +1,47 @@
use std::collections::HashMap;

use super::Type;
use super::TypeIdentifierTree;

pub fn builtin_types() -> HashMap<String, Type> {
pub fn builtin_types() -> HashMap<String, TypeIdentifierTree> {
let mut builtins = HashMap::new();

builtins.insert(
"assert".to_owned(),
Type::Fn {
args_t: vec![Type::Bool],
ret_t: Box::new(Type::Void),
uses_self: false,
TypeIdentifierTree {
root: "fn".into(),
children: vec![
// return value comes first for functions in type identifier trees
"void".into(),
"bool".into(),
],
},
);
builtins.insert(
"assert_eq".to_owned(),
Type::Fn {
args_t: vec![Type::Any, Type::Any],
ret_t: Box::new(Type::Void),
uses_self: false,
TypeIdentifierTree {
root: "fn".into(),
children: vec!["any".into(), "any".into()],
},
);
builtins.insert(
"dbg".to_owned(),
Type::Fn {
args_t: vec![Type::Any],
ret_t: Box::new(Type::Void),
uses_self: false,
TypeIdentifierTree {
root: "fn".into(),
children: vec!["void".into(), "any".into()],
},
);
builtins.insert(
"print".to_owned(),
Type::Fn {
args_t: vec![Type::Any],
ret_t: Box::new(Type::Void),
uses_self: false,
TypeIdentifierTree {
root: "fn".into(),
children: vec!["void".into(), "any".into()],
},
);
builtins.insert(
"println".to_owned(),
Type::Fn {
args_t: vec![Type::Any],
ret_t: Box::new(Type::Void),
uses_self: false,
TypeIdentifierTree {
root: "fn".into(),
children: vec!["void".into(), "any".into()],
},
);

Expand Down
32 changes: 16 additions & 16 deletions coal-core/src/ast/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ use std::fmt;

use crate::{ParserError, ParserErrorKind, Span, indent};

use super::{Func, Ident, Infix, Literal, Param, Prefix, Stmt, Struct, Type};
use super::{BaseType, Func, Ident, Infix, Literal, Param, Prefix, ResolvedType, Stmt, Struct};

#[derive(Clone, Debug, PartialEq)]
pub enum Expr {
Ident(Ident, Type, Span),
Ident(Ident, ResolvedType, Span),
Literal(Literal, Span),
Prefix(Prefix, Box<Expr>, Span),
Infix(Infix, Box<Expr>, Box<Expr>, Span),
Expand All @@ -33,28 +33,28 @@ pub enum Expr {
Fn(Func),
Closure {
args: Vec<Param>,
ret_t: Type,
ret_t: ResolvedType,
body: Vec<Stmt>,
span: Span,
},
Struct(Struct, Span),
Call {
name: String,
args: Vec<Expr>,
ret_t: Type,
ret_t: ResolvedType,
span: Span,
},
MethodCall {
lhs: Box<Expr>,
name: String,
args: Vec<Expr>,
ret_t: Type,
ret_t: ResolvedType,
span: Span,
},
AttrAccess {
lhs: Box<Expr>,
name: String,
t: Type,
t: ResolvedType,
span: Span,
},
}
Expand Down Expand Up @@ -88,12 +88,12 @@ impl Expr {

pub fn is_indexable(&self) -> bool {
match self {
Expr::Ident(_, t, _) => t.is_indexable(),
Expr::Ident(_, t, _) => t.base.is_indexable(),
Expr::Literal(l, _) => l.is_indexable(),
Expr::Prefix(_, rhs, _) => rhs.is_indexable(),
Expr::Infix(_, lhs, rhs, _) => lhs.is_indexable() && rhs.is_indexable(),
Expr::Index(lhs, _, _) => lhs.is_indexable(),
Expr::Call { ret_t, .. } => ret_t.is_indexable(),
Expr::Call { ret_t, .. } => ret_t.base.is_indexable(),
_ => false,
}
}
Expand All @@ -102,15 +102,15 @@ impl Expr {
matches!(self, Expr::Fn(_) | Expr::Closure { .. })
}

pub fn ret_t(&self, expected: &Type, last: bool) -> Result<Type, ParserError> {
pub fn ret_t(&self, expected: &ResolvedType, last: bool) -> Result<ResolvedType, ParserError> {
match self {
Expr::If {
then, elifs, alt, ..
} => {
let mut returning = None;
for stmt in then {
let t = stmt.ret_t(expected, last)?;
if t != Type::Void && t != *expected {
if t.base != BaseType::Void && t != *expected {
return Err(ParserError::new(
ParserErrorKind::TypeMismatch(
expected.clone().into(),
Expand Down Expand Up @@ -159,18 +159,18 @@ impl Expr {
));
}
}
} else if last && *expected != Type::Void {
} else if last && expected.base != BaseType::Void {
return Err(ParserError::new(
ParserErrorKind::MissingElseClause,
self.span(),
));
}
Ok(Type::Void)
Ok(BaseType::Void.try_into().unwrap())
}
Expr::While { body, .. } => {
for stmt in body {
let t = stmt.ret_t(expected, last)?;
if t != Type::Void && t != *expected {
if t.base != BaseType::Void && t != *expected {
return Err(ParserError::new(
ParserErrorKind::TypeMismatch(
expected.clone().into(),
Expand All @@ -180,9 +180,9 @@ impl Expr {
));
}
}
Ok(Type::Void)
Ok(BaseType::Void.try_into().unwrap())
}
_ => Ok(Type::Void),
_ => Ok(BaseType::Void.try_into().unwrap()),
}
}

Expand Down Expand Up @@ -219,7 +219,7 @@ impl Expr {
rets
}

pub fn cast(&self, to: &Type) -> Expr {
pub fn cast(&self, to: &ResolvedType) -> Expr {
match self {
Expr::Literal(l, _) => Expr::Literal(l.cast(to), self.span()),
_ => self.clone(),
Expand Down
6 changes: 3 additions & 3 deletions coal-core/src/ast/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ use std::{

use crate::{Span, indent};

use super::{Param, Stmt, Type};
use super::{BaseType, Param, ResolvedType, Stmt};

#[derive(Clone, Debug, PartialEq)]
pub struct Func {
pub name: String,
pub args: Vec<Param>,
pub ret_t: Type,
pub ret_t: ResolvedType,
pub body: Vec<Stmt>,
pub span: Span,
}
Expand All @@ -37,7 +37,7 @@ impl Func {
.map(|arg| format!("{arg}"))
.collect::<Vec<String>>()
.join(", ");
if *ret_t == Type::Void {
if ret_t.base == BaseType::Void {
writeln!(f, "{args}) {{")?;
} else {
writeln!(f, "{args}) -> {ret_t} {{")?;
Expand Down
8 changes: 4 additions & 4 deletions coal-core/src/ast/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,25 @@ use std::{

use crate::indent;

use super::{Expr, Type};
use super::{Expr, ResolvedType};

#[derive(Clone, Debug, PartialEq, Default)]
pub struct List {
pub data: Vec<Expr>,
pub t: Type,
pub t: ResolvedType,
pub repeat: Option<Box<Expr>>,
}

impl List {
pub fn new(data: &[Expr], t: Type) -> Self {
pub fn new(data: &[Expr], t: ResolvedType) -> Self {
List {
data: data.to_owned(),
t,
repeat: None,
}
}

pub fn new_repeat(data: &[Expr], t: Type, repeat: Box<Expr>) -> Self {
pub fn new_repeat(data: &[Expr], t: ResolvedType, repeat: Box<Expr>) -> Self {
List {
data: data.to_owned(),
t,
Expand Down
10 changes: 5 additions & 5 deletions coal-core/src/ast/literal.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::fmt;

use crate::indent;
use crate::{ResolvedType, indent};

use super::{F32, F64, I32, I64, I128, List, Map, Type, U32, U64};
use super::{F32, F64, I32, I64, I128, List, Map, U32, U64};

#[derive(Clone, Debug, PartialEq)]
pub enum Literal {
Expand Down Expand Up @@ -49,7 +49,7 @@ impl Literal {
}
}

pub fn set_type(&mut self, t1: Type, t2: Option<Type>) {
pub fn set_type(&mut self, t1: ResolvedType, t2: Option<ResolvedType>) {
match self {
Literal::List(l) => l.t = t1,
Literal::Map(m) => {
Expand All @@ -62,8 +62,8 @@ impl Literal {
}
}

pub fn cast(&self, to: &Type) -> Literal {
match (self, to) {
pub fn cast(&self, to: &ResolvedType) -> Literal {
match (self, &to.base) {
(Literal::U32(from), &U64) => Literal::U64(*from as u64),
(Literal::U32(from), &I32) => Literal::I32(*from as i32),
(Literal::U32(from), &I64) => Literal::I64(*from as i64),
Expand Down
11 changes: 7 additions & 4 deletions coal-core/src/ast/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ use std::fmt;

use crate::indent;

use super::{Expr, Type};
use super::{BaseType, Expr, ResolvedType};

#[derive(Clone, Debug, PartialEq)]
pub struct Map {
pub data: Vec<(Expr, Expr)>,
pub t: (Type, Type),
pub t: (ResolvedType, ResolvedType),
}

impl Map {
pub fn new(data: &[(Expr, Expr)], t: (Type, Type)) -> Self {
pub fn new(data: &[(Expr, Expr)], t: (ResolvedType, ResolvedType)) -> Self {
Map {
data: data.to_owned(),
t,
Expand Down Expand Up @@ -66,7 +66,10 @@ impl Default for Map {
fn default() -> Self {
Map {
data: vec![],
t: (Type::Unknown, Type::Unknown),
t: (
BaseType::Unknown.try_into().unwrap(),
BaseType::Unknown.try_into().unwrap(),
),
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions coal-core/src/ast/param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ use std::{
hash::{Hash, Hasher},
};

use crate::{Type, indent};
use crate::{ResolvedType, indent};

#[derive(Clone, Debug, PartialEq)]
pub struct Param {
pub name: String,
pub t: Type,
pub t: ResolvedType,
}

impl Param {
pub fn new(name: &str, t: Type) -> Param {
pub fn new(name: &str, t: ResolvedType) -> Param {
Param {
name: name.to_string(),
t,
Expand Down
17 changes: 10 additions & 7 deletions coal-core/src/ast/stmt.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use std::fmt;

use crate::{ParserError, ParserErrorKind, Span, indent};
use crate::{ParserError, ParserErrorKind, ResolvedType, Span, indent};

use super::{Comment, Expr, Ident, Infix, StructDecl, Type};
use super::{BaseType, Comment, Expr, Ident, Infix, StructDecl};

#[derive(Clone, Debug, PartialEq)]
pub enum Stmt {
Void,
Newline,
Comment(Comment),
Let(Ident, Type, Expr),
Let(Ident, ResolvedType, Expr),
Assign(Expr, Expr),
OpAssign(Infix, Expr, Expr),
Return(Expr),
Expand All @@ -30,16 +30,19 @@ impl Stmt {
}
}

pub fn ret_t(&self, expected: &Type, last: bool) -> Result<Type, ParserError> {
pub fn ret_t(&self, expected: &ResolvedType, last: bool) -> Result<ResolvedType, ParserError> {
match self {
Stmt::Return(e) => Type::try_from(e).map_err(|_| {
Stmt::Return(e) => ResolvedType::try_from(e).map_err(|_| {
ParserError::new(
ParserErrorKind::TypeMismatch(expected.clone().into(), Type::Void.into()),
ParserErrorKind::TypeMismatch(
expected.clone().into(),
ResolvedType::try_from(BaseType::Void).unwrap().into(),
),
e.span(),
)
}),
Stmt::Expr(e) => e.ret_t(expected, last),
_ => Ok(Type::Void),
_ => Ok(BaseType::Void.try_into().unwrap()),
}
}

Expand Down
Loading