mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
REFACTOR: Move the ucg IR into it's own module.
This commit is contained in:
parent
3ed8fe332f
commit
ae419ea3e7
219
src/build/ir.rs
Normal file
219
src/build/ir.rs
Normal file
@ -0,0 +1,219 @@
|
||||
//! The ir module holds the definitions of our ucg Intermediate Representation before it is converted
|
||||
//! to an output artifact.
|
||||
use std::convert::From;
|
||||
use std::fmt;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::rc::Rc;
|
||||
use std::string::ToString;
|
||||
|
||||
use ast::*;
|
||||
use error;
|
||||
|
||||
/// The Intermediate representation of a compiled UCG AST.
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub enum Val {
|
||||
Empty,
|
||||
Boolean(bool),
|
||||
Int(i64),
|
||||
Float(f64),
|
||||
Str(String),
|
||||
List(Vec<Rc<Val>>),
|
||||
Tuple(Vec<(Positioned<String>, Rc<Val>)>),
|
||||
Macro(MacroDef),
|
||||
}
|
||||
|
||||
impl Val {
|
||||
/// Returns the Type of a Val as a string.
|
||||
pub fn type_name(&self) -> String {
|
||||
match self {
|
||||
&Val::Empty => "EmptyValue".to_string(),
|
||||
&Val::Boolean(_) => "Boolean".to_string(),
|
||||
&Val::Int(_) => "Integer".to_string(),
|
||||
&Val::Float(_) => "Float".to_string(),
|
||||
&Val::Str(_) => "String".to_string(),
|
||||
&Val::List(_) => "List".to_string(),
|
||||
&Val::Tuple(_) => "Tuple".to_string(),
|
||||
&Val::Macro(_) => "Macro".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if called with a Val of the same type as itself.
|
||||
pub fn type_equal(&self, target: &Self) -> bool {
|
||||
enum_type_equality!(
|
||||
self,
|
||||
target,
|
||||
&Val::Empty,
|
||||
&Val::Boolean(_),
|
||||
&Val::Int(_),
|
||||
&Val::Float(_),
|
||||
&Val::Str(_),
|
||||
&Val::List(_),
|
||||
&Val::Tuple(_),
|
||||
&Val::Macro(_)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn equal(
|
||||
&self,
|
||||
target: &Self,
|
||||
file_name: &str,
|
||||
pos: Position,
|
||||
) -> Result<bool, error::Error> {
|
||||
// first we do a type equality comparison
|
||||
match (self, target) {
|
||||
// Empty values are always equal.
|
||||
(&Val::Empty, &Val::Empty) => Ok(true),
|
||||
(&Val::Int(ref i), &Val::Int(ref ii)) => Ok(i == ii),
|
||||
(&Val::Float(ref f), &Val::Float(ref ff)) => Ok(f == ff),
|
||||
(&Val::Boolean(ref b), &Val::Boolean(ref bb)) => Ok(b == bb),
|
||||
(&Val::Str(ref s), &Val::Str(ref ss)) => Ok(s == ss),
|
||||
(&Val::List(ref ldef), &Val::List(ref rdef)) => {
|
||||
if ldef.len() != rdef.len() {
|
||||
Ok(false)
|
||||
} else {
|
||||
for (i, lv) in ldef.iter().enumerate() {
|
||||
try!(lv.equal(rdef[i].as_ref(), file_name, pos.clone()));
|
||||
}
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
(&Val::Tuple(ref ldef), &Val::Tuple(ref rdef)) => {
|
||||
if ldef.len() != rdef.len() {
|
||||
Ok(false)
|
||||
} else {
|
||||
for (i, lv) in ldef.iter().enumerate() {
|
||||
let field_target = &rdef[i];
|
||||
if lv.0.val != field_target.0.val {
|
||||
// field name equality
|
||||
return Ok(false);
|
||||
} else {
|
||||
// field value equality.
|
||||
if !try!(lv.1.equal(
|
||||
field_target.1.as_ref(),
|
||||
file_name,
|
||||
lv.0.pos.clone()
|
||||
)) {
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
(&Val::Macro(_), &Val::Macro(_)) => Err(error::Error::new(
|
||||
format!("Macros are not comparable in file: {}", file_name),
|
||||
error::ErrorType::TypeFail,
|
||||
pos,
|
||||
)),
|
||||
(me, tgt) => Err(error::Error::new(
|
||||
format!("Types differ for {}, {} in file: {}", me, tgt, file_name),
|
||||
error::ErrorType::TypeFail,
|
||||
pos,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the fields if this Val is a tuple. None otherwise.
|
||||
pub fn get_fields(&self) -> Option<&Vec<(Positioned<String>, Rc<Val>)>> {
|
||||
if let &Val::Tuple(ref fs) = self {
|
||||
Some(fs)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_int(&self) -> bool {
|
||||
if let &Val::Int(_) = self {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
if let &Val::Empty = self {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn is_float(&self) -> bool {
|
||||
if let &Val::Float(_) = self {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn is_string(&self) -> bool {
|
||||
if let &Val::Str(_) = self {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn is_tuple(&self) -> bool {
|
||||
if let &Val::Tuple(_) = self {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn is_list(&self) -> bool {
|
||||
if let &Val::List(_) = self {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn is_macro(&self) -> bool {
|
||||
if let &Val::Macro(_) = self {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Val {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
match self {
|
||||
&Val::Boolean(b) => write!(f, "Boolean({})", b),
|
||||
&Val::Empty => write!(f, "EmptyValue"),
|
||||
&Val::Float(ref ff) => write!(f, "Float({})", ff),
|
||||
&Val::Int(ref i) => write!(f, "Int({})", i),
|
||||
&Val::Str(ref s) => write!(f, "String({})", s),
|
||||
&Val::List(ref def) => {
|
||||
try!(write!(f, "[\n"));
|
||||
for v in def.iter() {
|
||||
try!(write!(f, "\t{},\n", v));
|
||||
}
|
||||
write!(f, "]")
|
||||
}
|
||||
&Val::Macro(_) => write!(f, "Macro(..)"),
|
||||
&Val::Tuple(ref def) => {
|
||||
try!(write!(f, "Tuple(\n"));
|
||||
for v in def.iter() {
|
||||
try!(write!(f, "\t{} = {},\n", v.0.val, v.1));
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Val> for String {
|
||||
fn from(v: Val) -> String {
|
||||
match v {
|
||||
Val::Int(ref i) => format!("{}", i),
|
||||
Val::Float(ref f) => format!("{}", f),
|
||||
Val::Str(ref s) => s.to_string(),
|
||||
Val::Boolean(ref b) => format!("{}", b),
|
||||
Val::Empty => "NULL".to_string(),
|
||||
val => format!("<{}>", val),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Val {
|
||||
fn from(s: String) -> Val {
|
||||
Val::Str(s)
|
||||
}
|
||||
}
|
215
src/build/mod.rs
215
src/build/mod.rs
@ -16,11 +16,8 @@
|
||||
use std::cell::RefCell;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::convert::From;
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::ops::Deref;
|
||||
@ -35,6 +32,9 @@ use parse::parse;
|
||||
use tokenizer::Span;
|
||||
|
||||
pub mod assets;
|
||||
pub mod ir;
|
||||
|
||||
pub use self::ir::Val;
|
||||
|
||||
impl MacroDef {
|
||||
/// Expands a ucg Macro using the given arguments into a new Tuple.
|
||||
@ -80,215 +80,6 @@ impl MacroDef {
|
||||
/// The result of a build.
|
||||
type BuildResult = Result<(), Box<Error>>;
|
||||
|
||||
/// The Intermediate representation of a compiled UCG AST.
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub enum Val {
|
||||
Empty,
|
||||
Boolean(bool),
|
||||
Int(i64),
|
||||
Float(f64),
|
||||
Str(String),
|
||||
List(Vec<Rc<Val>>),
|
||||
Tuple(Vec<(Positioned<String>, Rc<Val>)>),
|
||||
Macro(MacroDef),
|
||||
}
|
||||
|
||||
impl Val {
|
||||
/// Returns the Type of a Val as a string.
|
||||
pub fn type_name(&self) -> String {
|
||||
match self {
|
||||
&Val::Empty => "EmptyValue".to_string(),
|
||||
&Val::Boolean(_) => "Boolean".to_string(),
|
||||
&Val::Int(_) => "Integer".to_string(),
|
||||
&Val::Float(_) => "Float".to_string(),
|
||||
&Val::Str(_) => "String".to_string(),
|
||||
&Val::List(_) => "List".to_string(),
|
||||
&Val::Tuple(_) => "Tuple".to_string(),
|
||||
&Val::Macro(_) => "Macro".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if called with a Val of the same type as itself.
|
||||
pub fn type_equal(&self, target: &Self) -> bool {
|
||||
enum_type_equality!(
|
||||
self,
|
||||
target,
|
||||
&Val::Empty,
|
||||
&Val::Boolean(_),
|
||||
&Val::Int(_),
|
||||
&Val::Float(_),
|
||||
&Val::Str(_),
|
||||
&Val::List(_),
|
||||
&Val::Tuple(_),
|
||||
&Val::Macro(_)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn equal(
|
||||
&self,
|
||||
target: &Self,
|
||||
file_name: &str,
|
||||
pos: Position,
|
||||
) -> Result<bool, error::Error> {
|
||||
// first we do a type equality comparison
|
||||
match (self, target) {
|
||||
// Empty values are always equal.
|
||||
(&Val::Empty, &Val::Empty) => Ok(true),
|
||||
(&Val::Int(ref i), &Val::Int(ref ii)) => Ok(i == ii),
|
||||
(&Val::Float(ref f), &Val::Float(ref ff)) => Ok(f == ff),
|
||||
(&Val::Boolean(ref b), &Val::Boolean(ref bb)) => Ok(b == bb),
|
||||
(&Val::Str(ref s), &Val::Str(ref ss)) => Ok(s == ss),
|
||||
(&Val::List(ref ldef), &Val::List(ref rdef)) => {
|
||||
if ldef.len() != rdef.len() {
|
||||
Ok(false)
|
||||
} else {
|
||||
for (i, lv) in ldef.iter().enumerate() {
|
||||
try!(lv.equal(rdef[i].as_ref(), file_name, pos.clone()));
|
||||
}
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
(&Val::Tuple(ref ldef), &Val::Tuple(ref rdef)) => {
|
||||
if ldef.len() != rdef.len() {
|
||||
Ok(false)
|
||||
} else {
|
||||
for (i, lv) in ldef.iter().enumerate() {
|
||||
let field_target = &rdef[i];
|
||||
if lv.0.val != field_target.0.val {
|
||||
// field name equality
|
||||
return Ok(false);
|
||||
} else {
|
||||
// field value equality.
|
||||
if !try!(lv.1.equal(
|
||||
field_target.1.as_ref(),
|
||||
file_name,
|
||||
lv.0.pos.clone()
|
||||
)) {
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
(&Val::Macro(_), &Val::Macro(_)) => Err(error::Error::new(
|
||||
format!("Macros are not comparable in file: {}", file_name),
|
||||
error::ErrorType::TypeFail,
|
||||
pos,
|
||||
)),
|
||||
(me, tgt) => Err(error::Error::new(
|
||||
format!("Types differ for {}, {} in file: {}", me, tgt, file_name),
|
||||
error::ErrorType::TypeFail,
|
||||
pos,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the fields if this Val is a tuple. None otherwise.
|
||||
pub fn get_fields(&self) -> Option<&Vec<(Positioned<String>, Rc<Val>)>> {
|
||||
if let &Val::Tuple(ref fs) = self {
|
||||
Some(fs)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_int(&self) -> bool {
|
||||
if let &Val::Int(_) = self {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
if let &Val::Empty = self {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn is_float(&self) -> bool {
|
||||
if let &Val::Float(_) = self {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn is_string(&self) -> bool {
|
||||
if let &Val::Str(_) = self {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn is_tuple(&self) -> bool {
|
||||
if let &Val::Tuple(_) = self {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn is_list(&self) -> bool {
|
||||
if let &Val::List(_) = self {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn is_macro(&self) -> bool {
|
||||
if let &Val::Macro(_) = self {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Val {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
match self {
|
||||
&Val::Boolean(b) => write!(f, "Boolean({})", b),
|
||||
&Val::Empty => write!(f, "EmptyValue"),
|
||||
&Val::Float(ref ff) => write!(f, "Float({})", ff),
|
||||
&Val::Int(ref i) => write!(f, "Int({})", i),
|
||||
&Val::Str(ref s) => write!(f, "String({})", s),
|
||||
&Val::List(ref def) => {
|
||||
try!(write!(f, "[\n"));
|
||||
for v in def.iter() {
|
||||
try!(write!(f, "\t{},\n", v));
|
||||
}
|
||||
write!(f, "]")
|
||||
}
|
||||
&Val::Macro(_) => write!(f, "Macro(..)"),
|
||||
&Val::Tuple(ref def) => {
|
||||
try!(write!(f, "Tuple(\n"));
|
||||
for v in def.iter() {
|
||||
try!(write!(f, "\t{} = {},\n", v.0.val, v.1));
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Val> for String {
|
||||
fn from(v: Val) -> String {
|
||||
match v {
|
||||
Val::Int(ref i) => format!("{}", i),
|
||||
Val::Float(ref f) => format!("{}", f),
|
||||
Val::Str(ref s) => s.to_string(),
|
||||
Val::Boolean(ref b) => format!("{}", b),
|
||||
Val::Empty => "NULL".to_string(),
|
||||
val => format!("<{}>", val),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Val {
|
||||
fn from(s: String) -> Val {
|
||||
Val::Str(s)
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines a set of values in a parsed file.
|
||||
type ValueMap = HashMap<Positioned<String>, Rc<Val>>;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user