ast: implement base value type

This commit is contained in:
anna 2021-04-19 19:17:22 +02:00
parent 0c1d66186e
commit a0e09b9613
Signed by: fef
GPG key ID: EC22E476DC2D3D84
3 changed files with 133 additions and 19 deletions

View file

@ -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<dyn Val>;
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<T: Clone> {
data: T,
}
/// Construct a new bool value
pub fn bool(val: bool) -> Box<dyn Val> {
Box::new(Data::new(val))
}
/// Construct a new int value
pub fn int(val: i64) -> Box<dyn Val> {
Box::new(Data::new(val))
}
/// Construct a new string value
pub fn string(val: &str) -> Box<dyn Val> {
Box::new(Data::new(String::from(val)))
}
impl<T: Clone> Data<T> {
pub fn new(data: T) -> Data<T> {
Data {
data
}
}
}
pub struct ValueError {
msg: String,
expected: Type,
actual: Type,
impl Val for Data<bool> {
fn clone(&self) -> Box<dyn Val> {
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<i64> {
fn clone(&self) -> Box<dyn Val> {
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<String> {
fn clone(&self) -> Box<dyn Val> {
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 <owo@fef.moe>

View file

@ -2,7 +2,7 @@
use std::str::Chars;
use cursor::Cursor;
use self::cursor::Cursor;
mod cursor;

View file

@ -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<String, Node>,