Skip to content

Commit

Permalink
refactor(runtime): Moved some methods to types
Browse files Browse the repository at this point in the history
  • Loading branch information
watcol committed Jul 26, 2022
1 parent d8c5566 commit 8e79b5b
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 102 deletions.
83 changes: 22 additions & 61 deletions drake-runtime/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
#![no_std]
extern crate alloc;

use alloc::string::String;
use alloc::vec;
use alloc::vec::Vec;
use core::ops::Range;
use drake_types::ast::{
Expression, ExpressionKind, Key, KeyKind, Literal, Pattern, PatternKind, Statement,
StatementKind, TableHeaderKind,
Expression, ExpressionKind, Literal, Pattern, PatternKind, Statement, StatementKind,
TableHeaderKind,
};
use drake_types::runtime::{Element, Error, Kind, Snapshot, Table, Value};
use drake_types::runtime::{Error, Kind, Snapshot, Table, Value};

#[derive(Clone, Debug, PartialEq)]
struct Environment<L> {
Expand Down Expand Up @@ -54,7 +53,9 @@ impl<L: Clone> Environment<L> {
}
};

table_insert(table, key, value, &mut self.errors);
if let Err(err) = table.insert(key, value) {
self.errors.push(err);
}
}

fn header(&mut self, kind: TableHeaderKind, pattern: Pattern<L>, mut default: Table<L>) {
Expand Down Expand Up @@ -150,7 +151,10 @@ pub fn evaluate<L: Clone>(ast: Vec<Statement<L>>) -> Snapshot<L> {
}
StatementKind::TableHeader(kind, pattern, default) => {
let default = default
.and_then(|expr| expr_to_table(expr, &mut env.errors))
.and_then(|expr| {
let (val, span) = expr_to_value(expr, &mut env.errors);
assert_table(val, span, &mut env.errors)
})
.unwrap_or_default();
env.header(kind, pattern, default)
}
Expand Down Expand Up @@ -181,7 +185,9 @@ fn expr_to_value<L: Clone>(
ExpressionKind::InlineTable(arr) => {
let mut table = Table::new();
for (key, expr) in arr {
table_insert(&mut table, key, expr_to_value(expr, errors).0, errors);
if let Err(err) = table.insert(key, expr_to_value(expr, errors).0) {
errors.push(err);
}
}
Value::Table(table)
}
Expand All @@ -197,65 +203,20 @@ fn expr_to_value<L: Clone>(
(val, expr.span)
}

fn expr_to_table<L: Clone>(expr: Expression<L>, errors: &mut Vec<Error<L>>) -> Option<Table<L>> {
match expr_to_value(expr, errors) {
(Value::Table(table), _) => Some(table),
(val, span) => {
fn assert_table<L: Clone>(
val: Value<L>,
span: Range<L>,
errors: &mut Vec<Error<L>>,
) -> Option<Table<L>> {
match val {
Value::Table(table) => Some(table),
val => {
errors.push(Error::KindMismatch {
expect: vec![Kind::Table],
found: Kind::from_value(&val),
found: val.kind(),
span,
});
None
}
}
}

fn table_insert<L: Clone>(
table: &mut Table<L>,
key: Key<L>,
value: Value<L>,
errors: &mut Vec<Error<L>>,
) {
let (global, name, span) = match key_destruct(key, errors) {
Some(key) => key,
None => return,
};

let table = if global {
&mut table.global
} else {
&mut table.local
};

if table.contains_key(&name) && !table[&name].default {
errors.push(Error::DuplicateKey {
existing: table[&name].defined.clone(),
found: span,
});
} else {
table.insert(
name,
Element {
value,
defined: span,
used: global,
default: false,
},
);
}
}

fn key_destruct<L>(key: Key<L>, errors: &mut Vec<Error<L>>) -> Option<(bool, String, Range<L>)> {
match key.kind {
KeyKind::Normal => Some((true, key.name, key.span)),
KeyKind::Local => Some((false, key.name, key.span)),
_ => {
errors.push(Error::NotSupported {
feature: "unknown keys",
span: key.span,
});
None
}
}
}
104 changes: 63 additions & 41 deletions drake-types/src/runtime.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
//! Types for runtimes
use crate::ast::{Key, KeyKind};
use alloc::string::String;
use alloc::vec::Vec;
use core::ops::Range;
use hashbrown::HashMap;

/// Snapshots for the runtime.
#[derive(Clone, Debug, PartialEq)]
pub struct Snapshot<L> {
pub root: Table<L>,
pub errors: Vec<Error<L>>,
}

/// Evaluated values
#[derive(Clone, Debug, PartialEq)]
#[non_exhaustive]
Expand All @@ -22,17 +30,31 @@ pub enum Value<L> {
Table(Table<L>),
}

/// Table's elements
#[derive(Clone, Debug, PartialEq)]
pub struct Element<L> {
/// A value of the element
pub value: Value<L>,
/// A position where the element is defined
pub defined: Range<L>,
/// A flag marks as the element is overridable.
pub default: bool,
/// A flag checks if the element is used, or not
pub used: bool,

impl<L> Value<L> {
/// Returns a kind of the value
pub fn kind(&self) -> Kind {
match self {
Self::Character(_) => Kind::Character,
Self::String(_) => Kind::String,
Self::Integer(_) => Kind::Integer,
Self::Float(_) => Kind::Float,
Self::Array(_) => Kind::Array,
Self::Table(_) => Kind::Table,
}
}
}

/// Name of value kinds for errors.
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum Kind {
Character,
String,
Integer,
Float,
Array,
Table,
}

/// Evaluated tables
Expand Down Expand Up @@ -66,13 +88,39 @@ impl<L> Table<L> {
.chain(self.local.values_mut())
.for_each(|elem| elem.default = true);
}

/// Inserts an element
pub fn insert(&mut self, key: Key<L>, value: Value<L>) -> Result<(), Error<L>> where L: Clone {
let (table, used) = match key.kind {
KeyKind::Normal => (&mut self.global, true),
KeyKind::Local => (&mut self.global, false),
};

if table.contains_key(&key.name) && !table[&key.name].default {
Err(Error::DuplicateKey { existing: table[&key.name].defined.clone(), found: key.span })
} else {
table.insert(key.name, Element {
value,
defined: key.span,
default: false,
used,
});
Ok(())
}
}
}

/// Snapshots for the runtime.
/// Table's elements
#[derive(Clone, Debug, PartialEq)]
pub struct Snapshot<L> {
pub root: Table<L>,
pub errors: Vec<Error<L>>,
pub struct Element<L> {
/// A value of the element
pub value: Value<L>,
/// A position where the element is defined
pub defined: Range<L>,
/// A flag marks as the element is overridable.
pub default: bool,
/// A flag checks if the element is used, or not
pub used: bool,
}

/// Errors for runtimes
Expand All @@ -97,29 +145,3 @@ pub enum Error<L> {
},
Unexpected,
}

/// Name of value kinds for errors.
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum Kind {
Character,
String,
Integer,
Float,
Array,
Table,
}

impl Kind {
/// Evaluates a kind from the value.
pub fn from_value<L>(val: &Value<L>) -> Self {
match val {
Value::Character(_) => Self::Character,
Value::String(_) => Self::String,
Value::Integer(_) => Self::Integer,
Value::Float(_) => Self::Float,
Value::Array(_) => Self::Array,
Value::Table(_) => Self::Table,
}
}
}

0 comments on commit 8e79b5b

Please sign in to comment.