summaryrefslogtreecommitdiffstats
path: root/crates
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2024-04-28 23:37:35 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2024-04-29 19:20:34 +0200
commit41982de3beb59b26c57f2627a7d74f223831e75f (patch)
treec6e23545df7da1723fb34302e39c2154b9f8cd1e /crates
parentf03f4dfc06ef0a2022b8cb35eced694ca07a063d (diff)
downloadrebel-41982de3beb59b26c57f2627a7d74f223831e75f.tar
rebel-41982de3beb59b26c57f2627a7d74f223831e75f.zip
rebel-lang: typing: implement turning an AST Type into a runtime Type
Diffstat (limited to 'crates')
-rw-r--r--crates/rebel-lang/src/typing.rs56
1 files changed, 55 insertions, 1 deletions
diff --git a/crates/rebel-lang/src/typing.rs b/crates/rebel-lang/src/typing.rs
index fc3009a..2af8d33 100644
--- a/crates/rebel-lang/src/typing.rs
+++ b/crates/rebel-lang/src/typing.rs
@@ -2,7 +2,7 @@ use std::{collections::HashMap, fmt::Display};
use enum_kinds::EnumKind;
-use rebel_parse::ast::{self, expr};
+use rebel_parse::ast::{self, expr, typ};
use crate::{func::FuncType, scope::Context};
@@ -79,6 +79,50 @@ impl Type {
})
}
+ pub fn ast_type(ctx: &Context, expr: &typ::Type<'_>) -> Result<Type> {
+ use typ::Type::*;
+
+ Ok(match expr {
+ Paren(subexpr) => Self::ast_type(ctx, subexpr)?,
+ Path(path) => Self::path_type(ctx, path)?,
+ Literal(lit) => Self::literal_type(ctx, lit)?,
+ })
+ }
+
+ fn path_type(ctx: &Context, path: &ast::Path<'_>) -> Result<Type> {
+ use Type::*;
+
+ if path.components == [ast::Ident { name: "_" }] {
+ return Ok(Free);
+ }
+
+ ctx.types.lookup(&path.components).cloned().ok_or(TypeError)
+ }
+
+ fn literal_type(ctx: &Context, lit: &typ::Literal<'_>) -> Result<Type> {
+ use typ::Literal;
+ use Type::*;
+
+ Ok(match lit {
+ Literal::Unit => Unit,
+ Literal::Tuple(elems) => Tuple(
+ elems
+ .iter()
+ .map(|elem| Self::ast_type(ctx, elem))
+ .collect::<Result<_>>()?,
+ ),
+ Literal::Array(typ, len) => Array(Box::new(Self::ast_type(ctx, typ)?), (*len).into()),
+ Literal::Struct(entries) => Struct(
+ entries
+ .iter()
+ .map(|typ::StructField { name, typ }| {
+ Ok(((*name).to_owned(), Self::ast_type(ctx, typ)?))
+ })
+ .collect::<Result<_>>()?,
+ ),
+ })
+ }
+
pub fn ast_stmt_type(ctx: &Context, stmt: &ast::BodyStmt<'_>) -> Result<Type> {
match stmt {
ast::BodyStmt::Assign { dest: _, expr } => {
@@ -417,6 +461,16 @@ impl ArrayLen {
}
}
+impl From<typ::ArrayLen> for ArrayLen {
+ fn from(value: typ::ArrayLen) -> Self {
+ match value {
+ typ::ArrayLen::Free => ArrayLen::Free,
+ typ::ArrayLen::Fixed(len) => ArrayLen::Fixed(len),
+ typ::ArrayLen::Dynamic => ArrayLen::Dynamic,
+ }
+ }
+}
+
impl Display for ArrayLen {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {