From a0e09b96131ad33500c75291f3140fe139b6a2c8 Mon Sep 17 00:00:00 2001 From: Felix Date: Mon, 19 Apr 2021 19:17:22 +0200 Subject: [PATCH] ast: implement base value type --- src/ast/val.rs | 141 ++++++++++++++++++++++++++++++++++++++++++++----- src/lex/mod.rs | 2 +- src/lib.rs | 9 ++-- 3 files changed, 133 insertions(+), 19 deletions(-) diff --git a/src/ast/val.rs b/src/ast/val.rs index 41b1a6a..de5e425 100644 --- a/src/ast/val.rs +++ b/src/ast/val.rs @@ -1,25 +1,138 @@ // See the end of this file for copyright and license terms. -pub enum Value { - Bool(bool), - Int(i64), - String(String), +use std::fmt; + +/// Any primitive data type a [`Val`](Val) can hold. +pub enum Type { + Bool, + Int, + String, } -impl Value { - pub fn type_name(&self) -> &'static str { - match self { - Value::Bool(_) => "boolean", - Value::Int(_) => "int", - Value::String(_) => "string", +pub trait Val { + fn clone(&self) -> Box; + + fn typ(&self) -> Type; + + fn bool(&self) -> Result<&bool, TypeError> { + Err(TypeError::new(self.typ(), Type::Bool)) + } + + fn int(&self) -> Result<&i64, TypeError> { + Err(TypeError::new(self.typ(), Type::Int)) + } + + fn string(&self) -> Result<&str, TypeError> { + Err(TypeError::new(self.typ(), Type::String)) + } +} + +/// The actual data structure behind [`Val`](Val) +struct Data { + data: T, +} + +/// Construct a new bool value +pub fn bool(val: bool) -> Box { + Box::new(Data::new(val)) +} + +/// Construct a new int value +pub fn int(val: i64) -> Box { + Box::new(Data::new(val)) +} + +/// Construct a new string value +pub fn string(val: &str) -> Box { + Box::new(Data::new(String::from(val))) +} + +impl Data { + pub fn new(data: T) -> Data { + Data { + data } } } -pub struct ValueError { - msg: String, - expected: Type, - actual: Type, +impl Val for Data { + fn clone(&self) -> Box { + Box::new(Data { + data: self.data + }) + } + + fn typ(&self) -> Type { + Type::Bool + } + + fn bool(&self) -> Result<&bool, TypeError> { + Ok(&self.data) + } +} + +impl Val for Data { + fn clone(&self) -> Box { + Box::new(Data { + data: self.data + }) + } + + fn typ(&self) -> Type { + Type::Int + } + + fn int(&self) -> Result<&i64, TypeError> { + Ok(&self.data) + } +} + +impl Val for Data { + fn clone(&self) -> Box { + Box::new(Data { + data: self.data.clone() + }) + } + + fn typ(&self) -> Type { + Type::String + } + + fn string(&self) -> Result<&str, TypeError> { + Ok(&self.data) + } +} + +pub struct TypeError { + pub msg: String, + pub actual: Type, + pub expected: Type, +} + +impl TypeError { + pub fn new(actual: Type, expected: Type) -> TypeError { + TypeError { + msg: format!("Cannot convert from {} to {}", actual, expected), + actual, + expected, + } + } +} + +impl Type { + pub fn name(&self) -> &'static str { + match self { + Type::Bool => "bool", + Type::Int => "int", + Type::String => "string", + } + } +} + +impl fmt::Display for Type { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "\"{}\"", self.name()) + } } // Copyright (C) 2021 Fefie diff --git a/src/lex/mod.rs b/src/lex/mod.rs index 5422519..7a6cc85 100644 --- a/src/lex/mod.rs +++ b/src/lex/mod.rs @@ -2,7 +2,7 @@ use std::str::Chars; -use cursor::Cursor; +use self::cursor::Cursor; mod cursor; diff --git a/src/lib.rs b/src/lib.rs index 668f922..f6b044b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,15 +1,16 @@ // See the end of this file for copyright and license terms. use std::collections::HashMap; +use std::collections::hash_map::Keys; use std::str::Chars; -pub mod lex; +mod lex; use crate::lex::{Lexer, SyntaxError}; -pub mod parser; - +mod parser; use parser::Parser; -use std::collections::hash_map::Keys; + +mod ast; pub struct Config { nodes: HashMap,