initial commit for tc, adds get_type to Node

This commit is contained in:
gluax 2022-05-03 11:26:56 -07:00
parent 46bd62870d
commit 4fb95d1195
33 changed files with 296 additions and 42 deletions

View File

@ -14,6 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_errors::Result;
use leo_span::{Span, Symbol};
use crate::Node;
@ -50,6 +51,10 @@ impl Node for Identifier {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
Ok(None)
}
}
impl Identifier {

View File

@ -156,4 +156,21 @@ impl Node for BinaryExpression {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
match self.op.class() {
BinaryOperationClass::Boolean => Ok(Some(Type::Boolean)),
BinaryOperationClass::Numeric => {
let left = self.left.get_type()?;
let right = self.right.get_type()?;
match (left, right) {
(Some(t1), Some(t2)) if t1 == t2 => Ok(Some(t1)),
(None, None) => Ok(None),
(Some(t1), Some(t2)) => todo!("throw err"),
(None, Some(t)) | (Some(t), None) => todo!("throw err"),
}
}
}
}
}

View File

@ -49,4 +49,8 @@ impl Node for CallExpression {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
Ok(None)
}
}

View File

@ -37,4 +37,8 @@ impl Node for ErrExpression {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
Ok(None)
}
}

View File

@ -14,8 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{GroupValue, Identifier, IntegerType, Node};
use crate::{GroupValue, Identifier, IntegerType, Node, Type};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -80,6 +80,19 @@ impl Node for Expression {
Err(n) => n.set_span(span),
}
}
fn get_type(&self) -> Result<Option<Type>> {
use Expression::*;
match self {
Identifier(n) => n.get_type(),
Value(n) => n.get_type(),
Binary(n) => n.get_type(),
Unary(n) => n.get_type(),
Ternary(n) => n.get_type(),
Call(n) => n.get_type(),
Err(n) => n.get_type(),
}
}
}
impl fmt::Display for Expression {

View File

@ -43,4 +43,8 @@ impl Node for TernaryExpression {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
Ok(None)
}
}

View File

@ -64,4 +64,8 @@ impl Node for UnaryExpression {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
self.inner.get_type()
}
}

View File

@ -33,8 +33,6 @@ pub enum ValueExpression {
/// A group literal, either product or affine.
/// For example, `42group` or `(12, 52)group`.
Group(Box<GroupValue>),
/// A negated non-integer literal, e.g., `-4.2`.
Implicit(String, #[serde(with = "leo_span::span_json")] Span),
/// An integer literal, e.g., `42`.
Integer(IntegerType, String, #[serde(with = "leo_span::span_json")] Span),
/// A string literal, e.g., `"foobar"`.
@ -49,7 +47,6 @@ impl fmt::Display for ValueExpression {
Boolean(boolean, _) => write!(f, "{}", boolean),
Char(character) => write!(f, "{}", character),
Field(field, _) => write!(f, "{}", field),
Implicit(implicit, _) => write!(f, "{}", implicit),
Integer(type_, value, _) => write!(f, "{}{}", value, type_),
Group(group) => write!(f, "{}", group),
String(string, _) => {
@ -66,12 +63,7 @@ impl Node for ValueExpression {
fn span(&self) -> &Span {
use ValueExpression::*;
match &self {
Address(_, span)
| Boolean(_, span)
| Field(_, span)
| Implicit(_, span)
| Integer(_, _, span)
| String(_, span) => span,
Address(_, span) | Boolean(_, span) | Field(_, span) | Integer(_, _, span) | String(_, span) => span,
Char(character) => &character.span,
Group(group) => match &**group {
GroupValue::Single(_, span) => span,
@ -83,12 +75,9 @@ impl Node for ValueExpression {
fn set_span(&mut self, new_span: Span) {
use ValueExpression::*;
match self {
Address(_, span)
| Boolean(_, span)
| Field(_, span)
| Implicit(_, span)
| Integer(_, _, span)
| String(_, span) => *span = new_span,
Address(_, span) | Boolean(_, span) | Field(_, span) | Integer(_, _, span) | String(_, span) => {
*span = new_span
}
Char(character) => character.span = new_span,
Group(group) => match &mut **group {
GroupValue::Single(_, span) => *span = new_span,
@ -96,4 +85,17 @@ impl Node for ValueExpression {
},
}
}
fn get_type(&self) -> Result<Option<crate::Type>> {
use ValueExpression::*;
Ok(Some(match &self {
Address(_, _) => Type::Address,
Boolean(_, _) => Type::Boolean,
Char(_) => Type::Char,
Field(_, _) => Type::Field,
Integer(type_, _, _) => Type::IntegerType(*type_),
Group(_) => Type::Group,
String(_, _) => return Ok(None),
}))
}
}

View File

@ -15,6 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Block, FunctionInput, Identifier, Node, Type};
use leo_errors::Result;
use leo_span::{sym, Span, Symbol};
use serde::{Deserialize, Serialize};
@ -92,4 +93,8 @@ impl Node for Function {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<Type>> {
Ok(Some(self.output.clone()))
}
}

View File

@ -15,6 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Identifier, Node, Type};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -99,4 +100,8 @@ impl Node for FunctionInputVariable {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<Type>> {
Ok(Some(self.type_.clone()))
}
}

View File

@ -15,6 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{FunctionInputVariable, Node};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -83,4 +84,11 @@ impl Node for FunctionInput {
Variable(variable) => variable.span = span,
}
}
fn get_type(&self) -> Result<Option<crate::Type>> {
use FunctionInput::*;
match self {
Variable(variable) => variable.get_type(),
}
}
}

View File

@ -42,11 +42,8 @@ impl TryFrom<(Type, Expression)> for InputValue {
Self::Boolean(bool_value)
}
(Type::Char, ValueExpression::Char(value)) => Self::Char(value),
(Type::Field, ValueExpression::Field(value, _) | ValueExpression::Implicit(value, _)) => {
Self::Field(value)
}
(Type::Field, ValueExpression::Field(value, _)) => Self::Field(value),
(Type::Group, ValueExpression::Group(value)) => Self::Group(*value),
(Type::IntegerType(type_), ValueExpression::Implicit(value, _)) => Self::Integer(type_, value),
(Type::IntegerType(expected), ValueExpression::Integer(actual, value, span)) => {
if expected == actual {
Self::Integer(expected, value)

View File

@ -14,8 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_errors::Result;
use leo_span::Span;
use crate::Type;
/// A node in the AST.
pub trait Node:
std::fmt::Debug + std::fmt::Display + Clone + PartialEq + Eq + serde::Serialize + serde::de::DeserializeOwned
@ -25,4 +28,7 @@ pub trait Node:
/// Sets the span of the node.
fn set_span(&mut self, span: Span);
/// Gets the type of the node if it exists.
fn get_type(&self) -> Result<Option<Type>>;
}

View File

@ -15,7 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Node};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -109,4 +109,8 @@ impl Node for AssignStatement {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
self.value.get_type()
}
}

View File

@ -14,7 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Node, Statement};
use crate::{Node, Statement, Type};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -51,4 +52,8 @@ impl Node for Block {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<Type>> {
Ok(None)
}
}

View File

@ -15,6 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Block, Expression, Node, Statement};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -51,4 +52,8 @@ impl Node for ConditionalStatement {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
Ok(None)
}
}

View File

@ -15,6 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Char, Expression, Node};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -54,4 +55,8 @@ impl Node for ConsoleArgs {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
Ok(None)
}
}

View File

@ -15,6 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ConsoleArgs, Expression, Node};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -58,4 +59,8 @@ impl Node for ConsoleFunction {
ConsoleFunction::Error(formatted) | ConsoleFunction::Log(formatted) => formatted.set_span(span),
}
}
fn get_type(&self) -> Result<Option<crate::Type>> {
Ok(None)
}
}

View File

@ -15,6 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ConsoleFunction, Node};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -49,4 +50,8 @@ impl Node for ConsoleStatement {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
Ok(None)
}
}

View File

@ -15,6 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Node, Type};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -72,4 +73,8 @@ impl Node for DefinitionStatement {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<Type>> {
Ok(Some(self.type_.clone()))
}
}

View File

@ -15,6 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Identifier, Node};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -45,4 +46,8 @@ impl Node for VariableName {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
Ok(None)
}
}

View File

@ -15,6 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Node};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -43,4 +44,8 @@ impl Node for ExpressionStatement {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
self.expression.get_type()
}
}

View File

@ -15,6 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Block, Expression, Identifier, Node, Type};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -59,4 +60,8 @@ impl Node for IterationStatement {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<Type>> {
Ok(Some(self.type_.clone()))
}
}

View File

@ -15,6 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Node};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -43,4 +44,8 @@ impl Node for ReturnStatement {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
self.expression.get_type()
}
}

View File

@ -14,7 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ConditionalStatement, Node};
use crate::{ConditionalStatement, Node, Type};
use leo_errors::Result;
use leo_span::Span;
use super::*;
@ -86,4 +87,18 @@ impl Node for Statement {
Block(n) => n.set_span(span),
}
}
fn get_type(&self) -> Result<Option<Type>> {
use Statement::*;
match self {
Return(n) => n.get_type(),
Definition(n) => n.get_type(),
Assign(n) => n.get_type(),
Conditional(n) => n.get_type(),
Iteration(n) => n.get_type(),
Console(n) => n.get_type(),
Expression(n) => n.get_type(),
Block(n) => n.get_type(),
}
}
}

View File

@ -76,10 +76,6 @@ fn with_handler<T>(
Ok(parsed)
}
fn implicit_value_expr() -> Expression {
Expression::Value(ValueExpression::Implicit("".into(), Span::default()))
}
fn tokenize(test: Test) -> Result<Vec<SpannedToken>, String> {
tokenizer::tokenize("test", &test.content).map_err(|x| x.to_string())
}
@ -105,7 +101,7 @@ impl Namespace for ParseExpressionNamespace {
create_session_if_not_set_then(|_| {
let tokenizer = tokenize(test)?;
if all_are_comments(&tokenizer) {
return Ok(yaml_or_fail(implicit_value_expr()));
return Ok(yaml_or_fail(""));
}
with_handler(tokenizer, |p| p.parse_expression()).map(yaml_or_fail)
})
@ -124,7 +120,7 @@ impl Namespace for ParseStatementNamespace {
let tokenizer = tokenize(test)?;
if all_are_comments(&tokenizer) {
return Ok(yaml_or_fail(Statement::Expression(ExpressionStatement {
expression: implicit_value_expr(),
expression: Expression::Value(ValueExpression::String(Vec::new(), Default::default())),
span: Span::default(),
})));
}

View File

@ -31,3 +31,6 @@ pub use self::pass::*;
pub mod symbol_table;
pub use symbol_table::*;
pub mod type_checker;
pub use type_checker::*;

View File

@ -53,6 +53,10 @@ impl<'a> SymbolTable<'a> {
self.functions.insert(symbol, function);
Ok(())
}
pub fn lookup_fn(&mut self, symbol: &Symbol) -> Option<&&'a Function> {
self.functions.get(symbol)
}
}
impl<'a> Display for SymbolTable<'a> {

View File

@ -0,0 +1,42 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::*;
use crate::TypeChecker;
impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {}
impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
fn visit_return(&mut self, input: &'a ReturnStatement) -> VisitResult {
let parent = self.parent.unwrap();
if let Some(func) = self.symbol_table.lookup_fn(&parent) {
// if func.get_type()? != input.get_type()? {
// // self.handler.emit_err(err);
// }
}
VisitResult::VisitChildren
}
}
impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
fn visit_function(&mut self, input: &'a Function) -> VisitResult {
self.symbol_table.clear_variables();
self.parent = Some(input.name());
VisitResult::VisitChildren
}
}

View File

@ -0,0 +1,36 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_errors::emitter::Handler;
use leo_span::Symbol;
use crate::SymbolTable;
pub struct TypeChecker<'a> {
pub(crate) symbol_table: SymbolTable<'a>,
pub(crate) handler: &'a Handler,
pub(crate) parent: Option<Symbol>,
}
impl<'a> TypeChecker<'a> {
pub fn new(symbol_table: SymbolTable<'a>, handler: &'a Handler) -> Self {
Self {
symbol_table,
handler,
parent: None,
}
}
}

View File

@ -0,0 +1,39 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
pub mod check;
pub use check::*;
pub mod checker;
pub use checker::*;
use crate::{Pass, SymbolTable};
use leo_ast::{Ast, VisitorDirector};
use leo_errors::{emitter::Handler, Result};
impl<'a> Pass<'a> for TypeChecker<'a> {
type Input = (&'a Ast, SymbolTable<'a>, &'a Handler);
type Output = Result<()>;
fn do_pass((ast, symbol_table, handler): Self::Input) -> Self::Output {
let mut visitor = VisitorDirector::new(TypeChecker::new(symbol_table, handler));
visitor.visit_program(ast.as_repr());
handler.last_err()?;
Ok(())
}
}

View File

@ -32,16 +32,7 @@ outputs:
col_stop: 9
path: ""
content: 456field
- Value:
Implicit:
- ""
- span:
line_start: 0
line_stop: 0
col_start: 0
col_stop: 0
path: ""
content: ""
- Value:
Field:
- "87377802873778028737780287377802873778028737780287377802873778028737780287377802"

View File

@ -5,8 +5,8 @@ outputs:
- Expression:
expression:
Value:
Implicit:
- ""
String:
- []
- span:
line_start: 0
line_stop: 0