Add all type parsing tests

This commit is contained in:
2026-02-05 11:40:49 +02:00
parent 4b61adea5d
commit 660b9245fb
4 changed files with 94 additions and 7 deletions

View File

@@ -1,8 +1,8 @@
use std::fmt::Display;
use std::{clone, collections::HashSet, fmt::Display};
use anyhow::bail;
use crate::{common::loc::LocBox, info, validator::predefined::{BuiltinType, get_builtin_from_name}};
use crate::{common::loc::LocBox, error, info, validator::predefined::{BuiltinType, get_builtin_from_name}};
use super::{expr::Expr, literal::Literal, Ident, Program};
@@ -75,6 +75,38 @@ impl Type {
}
}
pub fn get_real_value_of_alias(&self, name: &Ident, program: &Program) -> anyhow::Result<Self> {
let mut used_types = HashSet::new();
used_types.insert(name.clone());
fn f(slf: &mut Type, program: &Program, used_types: &mut HashSet<Ident>) -> anyhow::Result<Type> {
match slf {
Type::Ref {inner, ..} => {
f(inner, program, used_types)
}
Type::Owned(ident) => {
if let Some(name) = used_types.get(ident) {
error!("Recursive type alias: {name}");
bail!("")
}
if let Some(t) = program.types.get(ident) {
used_types.insert(ident.clone());
let mut t = t.inner().clone();
f(&mut t, program, used_types)
} else {
Ok(slf.clone())
}
}
Type::SizedArray { inner, .. } |
Type::UnsizedArray { inner } => {
f(inner, program, used_types)
}
Type::Builtin { .. } => Ok(slf.clone()),
}
}
let mut t = self.clone();
f(&mut t, program, &mut used_types)
}
pub fn get_absolute_value(&self, program: &Program) -> anyhow::Result<Self> {
match self {
Self::Ref { inner, .. } => inner.get_absolute_value(program),

View File

@@ -1,6 +1,6 @@
use anyhow::{Result, bail};
use crate::{cli::CliArgs, common::loc::LocBox, lerror, parser::{Delimiter, ast::{Program, expr::Expr, literal::Literal}}, tokeniser::Token, validator::predefined::get_builtin_from_name};
use crate::{cli::CliArgs, common::loc::LocBox, lerror, parser::{Delimiter, ast::{Ident, Program, expr::Expr, literal::Literal}}, tokeniser::Token, validator::predefined::get_builtin_from_name};
use super::{ast::{typ::Type, TokenType}, expr::parse_expr, utils, Keyword, Punctuation};

View File

@@ -2,7 +2,7 @@ use std::{collections::HashMap, panic};
use anyhow::bail;
use crate::{common::{Loc, loc::LocBox}, parser::ast::{Ast, Program, Punctuation, Scope, TokenType, expr::*, literal::Literal, statement::*, typ::Type}, validator::predefined::get_builtin_from_name};
use crate::{common::{Loc, loc::LocBox}, parser::ast::{Ast, Ident, Program, Punctuation, Scope, TokenType, expr::*, literal::Literal, statement::*, typ::Type}, validator::predefined::get_builtin_from_name};
pub mod predefined;
@@ -669,7 +669,7 @@ fn check_that_types_exist_for_items(prog: &mut Program, items: &Vec<Ast>) -> any
Ok(())
}
fn validate_type(prog: &mut Program, typ: &LocBox<Type>) -> anyhow::Result<Type> {
pub fn validate_type(prog: &mut Program, typ: &LocBox<Type>) -> anyhow::Result<Type> {
fn f(prog: &mut Program, typ: &Type, loc: &Loc) -> anyhow::Result<Type> {
match typ {
Type::SizedArray { .. } |
@@ -691,7 +691,7 @@ fn validate_type(prog: &mut Program, typ: &LocBox<Type>) -> anyhow::Result<Type>
Type::Builtin { .. } => Ok(typ.clone())
}
}
f(prog, typ.inner(), typ.loc())
f(prog, &typ.inner().get_real_value_of_alias(&Ident::new(""), prog)?, typ.loc())
}

View File

@@ -1,6 +1,7 @@
use std::vec;
use mclangc::{common::{Loc, loc::LocBox}, parser::{self, ast::{Ident, Keyword, Program, Punctuation, TokenType, statement::{Enum, Struct}, typ::Type}}, tokeniser::Token, validator::predefined::{BuiltinType, get_builtin_from_name, load_builtin}};
use anyhow::bail;
use mclangc::{common::{Loc, loc::LocBox}, parser::{self, ast::{Ident, Keyword, Program, Punctuation, TokenType, statement::{Enum, Struct}, typ::Type}}, tokeniser::Token, validator::{self, predefined::{BuiltinType, get_builtin_from_name, load_builtin}}};
@@ -20,9 +21,63 @@ fn get_prog() -> Program {
name: Ident::new("MyEnum"),
fields: vec![],
}));
prog.types.insert(Ident::new("MyType"), LocBox::new(&loc, Type::Owned(Ident::new("MyStruct"))));
prog.types.insert(Ident::new("MyType2"), LocBox::new(&loc, Type::Owned(Ident::new("MyType"))));
prog.types.insert(Ident::new("MyType3"), LocBox::new(&loc, Type::Owned(Ident::new("MyType2")).as_ref()));
prog.types.insert(Ident::new("MyTypeInf"), LocBox::new(&loc, Type::Owned(Ident::new("MyTypeInf"))));
prog.types.insert(Ident::new("MyTypeInfIndirect"), LocBox::new(&loc, Type::Owned(Ident::new("MyType4"))));
prog.types.insert(Ident::new("MyType4"), LocBox::new(&loc, Type::Owned(Ident::new("MyType5"))));
prog.types.insert(Ident::new("MyType5"), LocBox::new(&loc, Type::Owned(Ident::new("MyType4"))));
prog
}
#[test]
fn parse_type_alias_simple() {
let mut tokens = vec![
Token::new_test(TokenType::Ident(Ident::new("MyType")))
];
let ret = parser::typ::parse_type(&mut tokens);
let mut prog = get_prog();
let ret = validator::validate_type(&mut prog, &ret.unwrap());
assert!(ret.is_ok());
assert_eq!(ret.unwrap(), Type::Owned(Ident::new("MyStruct")))
}
#[test]
fn parse_type_alias_deep() {
let mut tokens = vec![
Token::new_test(TokenType::Ident(Ident::new("MyType3")))
];
let ret = parser::typ::parse_type(&mut tokens);
let mut prog = get_prog();
let ret = validator::validate_type(&mut prog, &ret.unwrap());
assert!(ret.is_ok());
assert_eq!(ret.unwrap(), Type::Owned(Ident::new("MyStruct")))
}
#[test]
fn parse_type_alias_recursive_simple() {
let mut tokens = vec![
Token::new_test(TokenType::Ident(Ident::new("MyTypeInf")))
];
let ret = parser::typ::parse_type(&mut tokens);
let mut prog = get_prog();
let ret = validator::validate_type(&mut prog, &ret.unwrap());
assert!(ret.is_err());
}
#[test]
fn parse_type_alias_recursive_indirect() {
let mut tokens = vec![
Token::new_test(TokenType::Ident(Ident::new("MyType4")))
];
let ret = parser::typ::parse_type(&mut tokens);
let mut prog = get_prog();
let ret = validator::validate_type(&mut prog, &ret.unwrap());
assert!(ret.is_err());
}
#[test]
fn parse_type_named_struct() {
let mut tokens = vec![