Add all type parsing tests
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
use std::fmt::Display;
|
use std::{clone, collections::HashSet, fmt::Display};
|
||||||
|
|
||||||
use anyhow::bail;
|
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};
|
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> {
|
pub fn get_absolute_value(&self, program: &Program) -> anyhow::Result<Self> {
|
||||||
match self {
|
match self {
|
||||||
Self::Ref { inner, .. } => inner.get_absolute_value(program),
|
Self::Ref { inner, .. } => inner.get_absolute_value(program),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use anyhow::{Result, bail};
|
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};
|
use super::{ast::{typ::Type, TokenType}, expr::parse_expr, utils, Keyword, Punctuation};
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::{collections::HashMap, panic};
|
|||||||
|
|
||||||
use anyhow::bail;
|
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;
|
pub mod predefined;
|
||||||
|
|
||||||
@@ -669,7 +669,7 @@ fn check_that_types_exist_for_items(prog: &mut Program, items: &Vec<Ast>) -> any
|
|||||||
Ok(())
|
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> {
|
fn f(prog: &mut Program, typ: &Type, loc: &Loc) -> anyhow::Result<Type> {
|
||||||
match typ {
|
match typ {
|
||||||
Type::SizedArray { .. } |
|
Type::SizedArray { .. } |
|
||||||
@@ -691,7 +691,7 @@ fn validate_type(prog: &mut Program, typ: &LocBox<Type>) -> anyhow::Result<Type>
|
|||||||
Type::Builtin { .. } => Ok(typ.clone())
|
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())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use std::vec;
|
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"),
|
name: Ident::new("MyEnum"),
|
||||||
fields: vec![],
|
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
|
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]
|
#[test]
|
||||||
fn parse_type_named_struct() {
|
fn parse_type_named_struct() {
|
||||||
let mut tokens = vec![
|
let mut tokens = vec![
|
||||||
|
|||||||
Reference in New Issue
Block a user