[fine] Parse alternate types
This commit is contained in:
parent
f7acfd588d
commit
afa4812074
10 changed files with 73 additions and 26 deletions
|
|
@ -658,7 +658,8 @@ fn compile_new_object_expression(c: &mut Compiler, t: TreeRef, tree: &Tree) -> C
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the correct constructor.
|
// Fetch the correct constructor.
|
||||||
let type_reference = tree.child_tree_of_kind(c.syntax, TreeKind::TypeExpression)?;
|
// TODO: Binding this type should be done by semantics, and we should borrow it.
|
||||||
|
let type_reference = tree.child_tree_of_kind(c.syntax, TreeKind::TypeIdentifier)?;
|
||||||
let identifier = type_reference.nth_token(0)?;
|
let identifier = type_reference.nth_token(0)?;
|
||||||
let environment = c.semantics.environment_of(t);
|
let environment = c.semantics.environment_of(t);
|
||||||
match environment.bind(identifier)? {
|
match environment.bind(identifier)? {
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,7 @@ impl<'a> std::ops::IndexMut<TreeRef> for SyntaxTree<'a> {
|
||||||
pub enum TreeKind {
|
pub enum TreeKind {
|
||||||
Error,
|
Error,
|
||||||
|
|
||||||
|
AlternateType,
|
||||||
Argument,
|
Argument,
|
||||||
ArgumentList,
|
ArgumentList,
|
||||||
BinaryExpression,
|
BinaryExpression,
|
||||||
|
|
@ -150,6 +151,7 @@ pub enum TreeKind {
|
||||||
SelfParameter,
|
SelfParameter,
|
||||||
SelfReference,
|
SelfReference,
|
||||||
TypeExpression,
|
TypeExpression,
|
||||||
|
TypeIdentifier,
|
||||||
TypeParameter,
|
TypeParameter,
|
||||||
TypeParameterList,
|
TypeParameterList,
|
||||||
UnaryExpression,
|
UnaryExpression,
|
||||||
|
|
@ -688,14 +690,27 @@ fn return_type(p: &mut CParser) {
|
||||||
fn type_expr(p: &mut CParser) {
|
fn type_expr(p: &mut CParser) {
|
||||||
let m = p.start();
|
let m = p.start();
|
||||||
|
|
||||||
// TODO: Other kinds of type expressions probably!
|
alternate_type(p);
|
||||||
p.expect(TokenKind::Identifier, "expected the identifier of a type");
|
|
||||||
|
|
||||||
|
p.end(m, TreeKind::TypeExpression);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn alternate_type(p: &mut CParser) {
|
||||||
|
let mut result = type_identifier(p);
|
||||||
|
while p.eat(TokenKind::Or) {
|
||||||
|
let m = p.start_before(result);
|
||||||
|
type_identifier(p);
|
||||||
|
result = p.end(m, TreeKind::AlternateType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn type_identifier(p: &mut CParser) -> MarkClosed {
|
||||||
|
let m = p.start();
|
||||||
|
p.expect(TokenKind::Identifier, "expected the identifier of a type");
|
||||||
if p.at(TokenKind::Less) {
|
if p.at(TokenKind::Less) {
|
||||||
type_parameter_list(p);
|
type_parameter_list(p);
|
||||||
}
|
}
|
||||||
|
p.end(m, TreeKind::TypeIdentifier)
|
||||||
p.end(m, TreeKind::TypeExpression);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_parameter_list(p: &mut CParser) {
|
fn type_parameter_list(p: &mut CParser) {
|
||||||
|
|
@ -1095,7 +1110,7 @@ fn object_constructor(p: &mut CParser) -> MarkClosed {
|
||||||
let m = p.start();
|
let m = p.start();
|
||||||
|
|
||||||
p.expect_start(TokenKind::New);
|
p.expect_start(TokenKind::New);
|
||||||
type_expr(p);
|
type_identifier(p);
|
||||||
if p.at(TokenKind::LeftBrace) {
|
if p.at(TokenKind::LeftBrace) {
|
||||||
field_list(p);
|
field_list(p);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,9 @@ pub enum Type {
|
||||||
// class need to be fetched explicitly from the semantics via the
|
// class need to be fetched explicitly from the semantics via the
|
||||||
// TreeRef and `Semantics::class_of`; they are computed lazily.
|
// TreeRef and `Semantics::class_of`; they are computed lazily.
|
||||||
Object(TreeRef, Rc<str>),
|
Object(TreeRef, Rc<str>),
|
||||||
|
|
||||||
|
// An alternate is one or another type.
|
||||||
|
Alternate(Box<Type>, Box<Type>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Type {
|
impl Type {
|
||||||
|
|
@ -204,6 +207,7 @@ impl fmt::Display for Type {
|
||||||
List(t) => write!(f, "list<{t}>"),
|
List(t) => write!(f, "list<{t}>"),
|
||||||
Object(_, name) => write!(f, "{} instance", name),
|
Object(_, name) => write!(f, "{} instance", name),
|
||||||
Class(_, name) => write!(f, "class {}", name),
|
Class(_, name) => write!(f, "class {}", name),
|
||||||
|
Alternate(l, r) => write!(f, "{l} or {r}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -592,7 +596,7 @@ impl<'a> Semantics<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let tree = &self.syntax_tree[t];
|
let tree = &self.syntax_tree[t];
|
||||||
eprintln!(">>> environment_of => {tree:?}");
|
// eprintln!(">>> environment_of => {tree:?}");
|
||||||
|
|
||||||
let parent = match self.logical_parents[t.index()] {
|
let parent = match self.logical_parents[t.index()] {
|
||||||
Some(t) => self.environment_of(t),
|
Some(t) => self.environment_of(t),
|
||||||
|
|
@ -613,7 +617,7 @@ impl<'a> Semantics<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
self.environments.borrow_mut()[t.index()] = Incremental::Complete(result.clone());
|
self.environments.borrow_mut()[t.index()] = Incremental::Complete(result.clone());
|
||||||
eprintln!("<<< environment_of => {tree:?}");
|
// eprintln!("<<< environment_of => {tree:?}");
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -986,11 +990,12 @@ impl<'a> Semantics<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let tree = &self.syntax_tree[t];
|
let tree = &self.syntax_tree[t];
|
||||||
eprintln!(">>> type_of => {tree:?}");
|
// eprintln!(">>> type_of => {tree:?}");
|
||||||
|
|
||||||
let result = match tree.kind {
|
let result = match tree.kind {
|
||||||
TreeKind::Error => Some(Type::Error),
|
TreeKind::Error => Some(Type::Error),
|
||||||
|
|
||||||
|
TreeKind::AlternateType => self.type_of_alternate_type(tree),
|
||||||
TreeKind::Argument => self.type_of_argument(tree),
|
TreeKind::Argument => self.type_of_argument(tree),
|
||||||
TreeKind::BinaryExpression => self.type_of_binary(tree),
|
TreeKind::BinaryExpression => self.type_of_binary(tree),
|
||||||
TreeKind::Block => self.type_of_block(tree),
|
TreeKind::Block => self.type_of_block(tree),
|
||||||
|
|
@ -1016,7 +1021,8 @@ impl<'a> Semantics<'a> {
|
||||||
TreeKind::ReturnType => self.type_of_return_type(tree),
|
TreeKind::ReturnType => self.type_of_return_type(tree),
|
||||||
TreeKind::SelfParameter => self.type_of_self_parameter(tree),
|
TreeKind::SelfParameter => self.type_of_self_parameter(tree),
|
||||||
TreeKind::SelfReference => self.type_of_self_reference(t, tree),
|
TreeKind::SelfReference => self.type_of_self_reference(t, tree),
|
||||||
TreeKind::TypeExpression => self.type_of_type_expr(t, tree),
|
TreeKind::TypeExpression => self.type_of_type_expr(tree),
|
||||||
|
TreeKind::TypeIdentifier => self.type_of_type_identifier(t, tree),
|
||||||
TreeKind::TypeParameter => self.type_of_type_parameter(tree),
|
TreeKind::TypeParameter => self.type_of_type_parameter(tree),
|
||||||
TreeKind::UnaryExpression => self.type_of_unary(tree),
|
TreeKind::UnaryExpression => self.type_of_unary(tree),
|
||||||
|
|
||||||
|
|
@ -1026,7 +1032,7 @@ impl<'a> Semantics<'a> {
|
||||||
// NOTE: These return `None` if they encounter some problem.
|
// NOTE: These return `None` if they encounter some problem.
|
||||||
let result = result.unwrap_or(Type::Error);
|
let result = result.unwrap_or(Type::Error);
|
||||||
self.types.borrow_mut()[t.index()] = Incremental::Complete(result.clone());
|
self.types.borrow_mut()[t.index()] = Incremental::Complete(result.clone());
|
||||||
eprintln!("<<< type_of => {tree:?}");
|
// eprintln!("<<< type_of => {tree:?}");
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
@ -1190,8 +1196,13 @@ impl<'a> Semantics<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_of_type_expr(&self, t: TreeRef, tree: &Tree) -> Option<Type> {
|
fn type_of_type_expr(&self, tree: &Tree) -> Option<Type> {
|
||||||
assert_eq!(tree.kind, TreeKind::TypeExpression);
|
assert_eq!(tree.kind, TreeKind::TypeExpression);
|
||||||
|
Some(self.type_of(tree.nth_tree(0)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn type_of_type_identifier(&self, t: TreeRef, tree: &Tree) -> Option<Type> {
|
||||||
|
assert_eq!(tree.kind, TreeKind::TypeIdentifier);
|
||||||
|
|
||||||
// TODO: This will *clearly* need to get better.
|
// TODO: This will *clearly* need to get better.
|
||||||
let token = tree.nth_token(0)?;
|
let token = tree.nth_token(0)?;
|
||||||
|
|
@ -1711,6 +1722,13 @@ impl<'a> Semantics<'a> {
|
||||||
Some(self.type_of(tree.nth_tree(0)?))
|
Some(self.type_of(tree.nth_tree(0)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn type_of_alternate_type(&self, tree: &Tree) -> Option<Type> {
|
||||||
|
// TODO: IDEA: nth_tree returns a bogus tree if not a tree, stop returning Option?
|
||||||
|
let left = self.type_of(tree.nth_tree(0)?);
|
||||||
|
let right = self.type_of(tree.nth_tree(2)?);
|
||||||
|
Some(Type::Alternate(Box::new(left), Box::new(right)))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn dump_compiler_state(&self, tr: Option<TreeRef>) {
|
pub fn dump_compiler_state(&self, tr: Option<TreeRef>) {
|
||||||
eprintln!("Parsed the tree as:");
|
eprintln!("Parsed the tree as:");
|
||||||
eprintln!("\n{}", self.syntax_tree.dump(true));
|
eprintln!("\n{}", self.syntax_tree.dump(true));
|
||||||
|
|
@ -1789,7 +1807,7 @@ pub fn check(s: &Semantics) {
|
||||||
TreeKind::Parameter => {
|
TreeKind::Parameter => {
|
||||||
let _ = s.type_of(t);
|
let _ = s.type_of(t);
|
||||||
}
|
}
|
||||||
TreeKind::TypeExpression => {
|
TreeKind::TypeExpression | TreeKind::AlternateType | TreeKind::TypeIdentifier => {
|
||||||
let _ = s.type_of(t);
|
let _ = s.type_of(t);
|
||||||
}
|
}
|
||||||
TreeKind::Block => {
|
TreeKind::Block => {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,8 @@ fun f3() {}
|
||||||
// | Identifier:'"x"'
|
// | Identifier:'"x"'
|
||||||
// | Colon:'":"'
|
// | Colon:'":"'
|
||||||
// | TypeExpression
|
// | TypeExpression
|
||||||
// | Identifier:'"f64"'
|
// | TypeIdentifier
|
||||||
|
// | Identifier:'"f64"'
|
||||||
// | Comma:'","'
|
// | Comma:'","'
|
||||||
// | Error:'"Error at 'fun': expect ')' to end a parameter list"'
|
// | Error:'"Error at 'fun': expect ')' to end a parameter list"'
|
||||||
// | FunctionDecl
|
// | FunctionDecl
|
||||||
|
|
@ -27,7 +28,8 @@ fun f3() {}
|
||||||
// | Identifier:'"x"'
|
// | Identifier:'"x"'
|
||||||
// | Colon:'":"'
|
// | Colon:'":"'
|
||||||
// | TypeExpression
|
// | TypeExpression
|
||||||
// | Identifier:'"f64"'
|
// | TypeIdentifier
|
||||||
|
// | Identifier:'"f64"'
|
||||||
// | Comma:'","'
|
// | Comma:'","'
|
||||||
// | Error
|
// | Error
|
||||||
// | Error:'"Error at ',': expected parameter"'
|
// | Error:'"Error at ',': expected parameter"'
|
||||||
|
|
@ -36,7 +38,8 @@ fun f3() {}
|
||||||
// | Identifier:'"z"'
|
// | Identifier:'"z"'
|
||||||
// | Colon:'":"'
|
// | Colon:'":"'
|
||||||
// | TypeExpression
|
// | TypeExpression
|
||||||
// | Identifier:'"f64"'
|
// | TypeIdentifier
|
||||||
|
// | Identifier:'"f64"'
|
||||||
// | RightParen:'")"'
|
// | RightParen:'")"'
|
||||||
// | Block
|
// | Block
|
||||||
// | LeftBrace:'"{"'
|
// | LeftBrace:'"{"'
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,8 @@ fun fib(n: f64) -> f64 {
|
||||||
// | Identifier:'"f1"'
|
// | Identifier:'"f1"'
|
||||||
// | Colon:'":"'
|
// | Colon:'":"'
|
||||||
// | TypeExpression
|
// | TypeExpression
|
||||||
// | Identifier:'"f64"'
|
// | TypeIdentifier
|
||||||
|
// | Identifier:'"f64"'
|
||||||
// | Comma:'","'
|
// | Comma:'","'
|
||||||
// | Error:'"Error at 'fun': expect ')' to end a parameter list"'
|
// | Error:'"Error at 'fun': expect ')' to end a parameter list"'
|
||||||
// | FunctionDecl
|
// | FunctionDecl
|
||||||
|
|
@ -27,12 +28,14 @@ fun fib(n: f64) -> f64 {
|
||||||
// | Identifier:'"n"'
|
// | Identifier:'"n"'
|
||||||
// | Colon:'":"'
|
// | Colon:'":"'
|
||||||
// | TypeExpression
|
// | TypeExpression
|
||||||
// | Identifier:'"f64"'
|
// | TypeIdentifier
|
||||||
|
// | Identifier:'"f64"'
|
||||||
// | RightParen:'")"'
|
// | RightParen:'")"'
|
||||||
// | ReturnType
|
// | ReturnType
|
||||||
// | Arrow:'"->"'
|
// | Arrow:'"->"'
|
||||||
// | TypeExpression
|
// | TypeExpression
|
||||||
// | Identifier:'"f64"'
|
// | TypeIdentifier
|
||||||
|
// | Identifier:'"f64"'
|
||||||
// | Block
|
// | Block
|
||||||
// | LeftBrace:'"{"'
|
// | LeftBrace:'"{"'
|
||||||
// | ExpressionStatement
|
// | ExpressionStatement
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,14 @@ fun test() -> f64 {
|
||||||
// | Identifier:'"x"'
|
// | Identifier:'"x"'
|
||||||
// | Colon:'":"'
|
// | Colon:'":"'
|
||||||
// | TypeExpression
|
// | TypeExpression
|
||||||
// | Identifier:'"f64"'
|
// | TypeIdentifier
|
||||||
|
// | Identifier:'"f64"'
|
||||||
// | RightParen:'")"'
|
// | RightParen:'")"'
|
||||||
// | ReturnType
|
// | ReturnType
|
||||||
// | Arrow:'"->"'
|
// | Arrow:'"->"'
|
||||||
// | TypeExpression
|
// | TypeExpression
|
||||||
// | Identifier:'"f64"'
|
// | TypeIdentifier
|
||||||
|
// | Identifier:'"f64"'
|
||||||
// | Block
|
// | Block
|
||||||
// | LeftBrace:'"{"'
|
// | LeftBrace:'"{"'
|
||||||
// | ExpressionStatement
|
// | ExpressionStatement
|
||||||
|
|
@ -45,7 +47,8 @@ fun test() -> f64 {
|
||||||
// | ReturnType
|
// | ReturnType
|
||||||
// | Arrow:'"->"'
|
// | Arrow:'"->"'
|
||||||
// | TypeExpression
|
// | TypeExpression
|
||||||
// | Identifier:'"f64"'
|
// | TypeIdentifier
|
||||||
|
// | Identifier:'"f64"'
|
||||||
// | Block
|
// | Block
|
||||||
// | LeftBrace:'"{"'
|
// | LeftBrace:'"{"'
|
||||||
// | ExpressionStatement
|
// | ExpressionStatement
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ fun test() -> f64 {
|
||||||
// | ReturnType
|
// | ReturnType
|
||||||
// | Arrow:'"->"'
|
// | Arrow:'"->"'
|
||||||
// | TypeExpression
|
// | TypeExpression
|
||||||
// | Identifier:'"f64"'
|
// | TypeIdentifier
|
||||||
|
// | Identifier:'"f64"'
|
||||||
// | Block
|
// | Block
|
||||||
// | LeftBrace:'"{"'
|
// | LeftBrace:'"{"'
|
||||||
// | ExpressionStatement
|
// | ExpressionStatement
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,8 @@ fun test() -> bool {
|
||||||
// | ReturnType
|
// | ReturnType
|
||||||
// | Arrow:'"->"'
|
// | Arrow:'"->"'
|
||||||
// | TypeExpression
|
// | TypeExpression
|
||||||
// | Identifier:'"bool"'
|
// | TypeIdentifier
|
||||||
|
// | Identifier:'"bool"'
|
||||||
// | Block
|
// | Block
|
||||||
// | LeftBrace:'"{"'
|
// | LeftBrace:'"{"'
|
||||||
// | ExpressionStatement
|
// | ExpressionStatement
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,8 @@ fun test() -> f64 {
|
||||||
// | ReturnType
|
// | ReturnType
|
||||||
// | Arrow:'"->"'
|
// | Arrow:'"->"'
|
||||||
// | TypeExpression
|
// | TypeExpression
|
||||||
// | Identifier:'"f64"'
|
// | TypeIdentifier
|
||||||
|
// | Identifier:'"f64"'
|
||||||
// | Block
|
// | Block
|
||||||
// | LeftBrace:'"{"'
|
// | LeftBrace:'"{"'
|
||||||
// | IfStatement
|
// | IfStatement
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,8 @@ fun test() -> f64 {
|
||||||
// | ReturnType
|
// | ReturnType
|
||||||
// | Arrow:'"->"'
|
// | Arrow:'"->"'
|
||||||
// | TypeExpression
|
// | TypeExpression
|
||||||
// | Identifier:'"f64"'
|
// | TypeIdentifier
|
||||||
|
// | Identifier:'"f64"'
|
||||||
// | Block
|
// | Block
|
||||||
// | LeftBrace:'"{"'
|
// | LeftBrace:'"{"'
|
||||||
// | ExpressionStatement
|
// | ExpressionStatement
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue