Skip to content

Commit

Permalink
Replace ImlValue::Unset by Option<ImlValue>
Browse files Browse the repository at this point in the history
  • Loading branch information
phorward committed Feb 3, 2024
1 parent 2c124ef commit 0c0fc44
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 76 deletions.
22 changes: 12 additions & 10 deletions src/compiler/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,10 +196,8 @@ fn traverse_node_value(scope: &Scope, node: &Dict, name: Option<String>) -> ImlV
assert!(children.len() <= 2);

// Evaluate default parameter
let mut default = ImlValue::Unset;

if children.len() == 2 {
default = traverse_node_static(
let default = if children.len() == 2 {
let default = traverse_node_static(
scope,
Some(name.clone()),
children[1].borrow().object::<Dict>().unwrap(),
Expand All @@ -214,7 +212,11 @@ fn traverse_node_value(scope: &Scope, node: &Dict, name: Option<String>) -> ImlV
),
);
}
}

Some(default)
} else {
None
};

if generics.insert(name.clone(), default).is_some() {
scope.error(
Expand Down Expand Up @@ -252,13 +254,13 @@ fn traverse_node_value(scope: &Scope, node: &Dict, name: Option<String>) -> ImlV
name.clone(),
if children.len() == 2 {
let default = children[1].borrow();
traverse_node_static(
Some(traverse_node_static(
scope,
None,
default.object::<Dict>().unwrap(),
)
))
} else {
ImlValue::Unset
None
},
)
.is_some()
Expand Down Expand Up @@ -331,7 +333,7 @@ fn traverse_node_value(scope: &Scope, node: &Dict, name: Option<String>) -> ImlV
let param = &genarg["children"].borrow();
let param = param.object::<Dict>().unwrap();

args.push((offset, traverse_node_static(scope, None, param)));
args.push((offset, Some(traverse_node_static(scope, None, param))));
}

"genarg_named" => {
Expand All @@ -356,7 +358,7 @@ fn traverse_node_value(scope: &Scope, node: &Dict, name: Option<String>) -> ImlV

nargs.insert(
ident.to_string(),
(offset, traverse_node_static(scope, None, param)),
(offset, Some(traverse_node_static(scope, None, param))),
);
}

Expand Down
59 changes: 31 additions & 28 deletions src/compiler/iml/imlparselet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,18 @@ during compilation.
*/
#[derive(Debug, Clone)]
pub(in crate::compiler) struct ImlParseletModel {
pub is_consuming: bool, // Flag if parselet is consuming
pub locals: usize, // Total number of local variables present (including arguments)
pub signature: IndexMap<String, ImlValue>, // Arguments signature with default values
pub is_consuming: bool, // Flag if parselet is consuming
pub locals: usize, // Total number of local variables present (including arguments)
pub signature: IndexMap<String, Option<ImlValue>>, // Arguments signature with default values
pub variables: IndexMap<String, usize>, // Named local variables
pub temporaries: Vec<usize>, // Unnamed temporary variables
pub begin: ImlOp, // Begin intermediate operations
pub end: ImlOp, // End intermediate operations
pub body: ImlOp, // Body intermediate Operations
pub begin: ImlOp, // Begin intermediate operations
pub end: ImlOp, // End intermediate operations
pub body: ImlOp, // Body intermediate Operations
}

impl ImlParseletModel {
pub fn new(signature: Option<IndexMap<String, ImlValue>>) -> Self {
pub fn new(signature: Option<IndexMap<String, Option<ImlValue>>>) -> Self {
let signature = signature.unwrap_or(IndexMap::new());
// Generate variables from signature, addresses are enumerated!
let variables = signature
Expand Down Expand Up @@ -105,18 +105,18 @@ is turned into a executable parselet.
#[derive(Debug)]
pub(in crate::compiler) struct ImlParseletInstance {
pub model: Rc<RefCell<ImlParseletModel>>, // Parselet base model
pub generics: IndexMap<String, ImlValue>, // Generic signature with default configuration
pub offset: Option<Offset>, // Offset of definition
pub name: Option<String>, // Assigned name from source (for debugging)
pub severity: u8, // Capture push severity
pub is_generated: bool, // Flag if parselet instance is auto-generated
pub generics: IndexMap<String, Option<ImlValue>>, // Generic signature with default configuration
pub offset: Option<Offset>, // Offset of definition
pub name: Option<String>, // Assigned name from source (for debugging)
pub severity: u8, // Capture push severity
pub is_generated: bool, // Flag if parselet instance is auto-generated
}

/** Representation of parselet instance in intermediate code. */
impl ImlParseletInstance {
pub fn new(
model: Option<ImlParseletModel>,
generics: Option<IndexMap<String, ImlValue>>,
generics: Option<IndexMap<String, Option<ImlValue>>>,
offset: Option<Offset>,
name: Option<String>,
severity: u8,
Expand Down Expand Up @@ -148,10 +148,10 @@ impl std::fmt::Display for ImlParseletInstance {
if !self.generics.is_empty() {
write!(f, "<")?;
for (i, (name, value)) in self.generics.iter().enumerate() {
if matches!(value, ImlValue::Unset) {
write!(f, "{}{}", if i > 0 { ", " } else { "" }, name)?;
} else {
if let Some(value) = value {
write!(f, "{}{}:{}", if i > 0 { ", " } else { "" }, name, value)?;
} else {
write!(f, "{}{}", if i > 0 { ", " } else { "" }, name)?;
}
}
write!(f, ">")?;
Expand Down Expand Up @@ -224,19 +224,22 @@ impl ImlParselet {

for (name, value) in generics.iter_mut() {
// Replace any generics until no more are open
while let ImlValue::Generic { name, .. } = value {
while let Some(ImlValue::Generic { name, .. }) = value {
*value = from.borrow().generics.get(name).unwrap().clone();
changes = true;
}

match value {
ImlValue::SelfValue | ImlValue::SelfToken => {
// Replace any references of self by from
*value = ImlValue::Parselet(from.clone());
changes = true;
if let Some(value) = value {
match value {
ImlValue::SelfValue | ImlValue::SelfToken => {
// Replace any references of self by from
*value = ImlValue::Parselet(from.clone());
changes = true;
}
_ => {}
}
ImlValue::Unset => required.push(name.to_string()),
_ => {}
} else {
required.push(name.to_string());
}
}

Expand Down Expand Up @@ -282,10 +285,10 @@ impl ImlParselet {
// Copy parameter name
var_value.0.clone(),
// Register default value, if any
match &var_value.1 {
ImlValue::Unset => None,
value => Some(program.register(value)),
},
var_value
.1
.as_ref()
.and_then(|value| Some(program.register(value))),
)
})
.collect(),
Expand Down
7 changes: 6 additions & 1 deletion src/compiler/iml/imlprogram.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,12 @@ impl ImlProgram {
}
ImlValue::Generic { name, .. } => {
// fixme: Is this still relevant???
finalize_value(&current.borrow().generics[name], current, visited, configs)
finalize_value(
current.borrow().generics[name].as_ref().unwrap(),
current,
visited,
configs,
)
}
_ => None,
}
Expand Down
87 changes: 50 additions & 37 deletions src/compiler/iml/imlvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ modified and resolved during the compilation process.
*/
#[derive(Debug, Clone, PartialEq, Eq)]
pub(in crate::compiler) enum ImlValue {
Unset, // Unset
Unresolved(Rc<RefCell<ImlValue>>), // Unresolved ImlValues are shared
SelfValue, // self-reference (value)
SelfToken, // Self-reference (consuming)
Expand All @@ -35,7 +34,7 @@ pub(in crate::compiler) enum ImlValue {
addr: usize, // Address
},
Generic {
// Known generic placeholder
// Generic placeholder
offset: Option<Offset>, // Source offset
name: String, // Identifier
},
Expand All @@ -46,11 +45,11 @@ pub(in crate::compiler) enum ImlValue {
},
Instance {
// Unresolved parselet instance definition
offset: Option<Offset>, // Source offset
target: Box<ImlValue>, // Instance target
args: Vec<(Option<Offset>, ImlValue)>, // Sequential generic args
nargs: IndexMap<String, (Option<Offset>, ImlValue)>, // Named generic args
severity: Option<u8>, // optional desired severity
offset: Option<Offset>, // Source offset
target: Box<ImlValue>, // Instance target
args: Vec<(Option<Offset>, Option<ImlValue>)>, // Sequential generic args
nargs: IndexMap<String, (Option<Offset>, Option<ImlValue>)>, // Named generic args
severity: Option<u8>, // optional desired severity
is_generated: bool,
},
}
Expand All @@ -70,7 +69,7 @@ impl ImlValue {
offset: None,
name: name.to_string(),
}),
args: vec![(offset, self)],
args: vec![(offset, Some(self))],
nargs: IndexMap::new(),
severity,
is_generated: true,
Expand Down Expand Up @@ -121,15 +120,19 @@ impl ImlValue {

// Resolve sequential generic args
for arg in args.iter_mut() {
if !arg.1.resolve(scope) {
is_resolved = false;
if let Some(arg) = arg.1.as_mut() {
if !arg.resolve(scope) {
is_resolved = false;
}
}
}

// Resolve named generic args
for narg in nargs.values_mut() {
if !narg.1.resolve(scope) {
is_resolved = false;
if let Some(narg) = narg.1.as_mut() {
if !narg.resolve(scope) {
is_resolved = false;
}
}
}

Expand All @@ -155,28 +158,30 @@ impl ImlValue {
};

// Check integrity of constant names
if let Self::Unset = arg.1 {
scope.error(
arg.0,
format!("Expecting argument for generic '{}'", name),
);
} else if arg.1.is_consuming() {
if !utils::identifier_is_consumable(name) {
if let (offset, Some(value)) = &arg {
if value.is_consuming() {
if !utils::identifier_is_consumable(name) {
scope.error(
*offset,
format!(
"Cannot assign consumable {} to non-consumable generic '{}'",
value, name
)
);
}
} else if utils::identifier_is_consumable(name) {
scope.error(
arg.0,
*offset,
format!(
"Cannot assign consumable {} to non-consumable generic '{}'",
arg.1, name
"Cannot assign non-consumable {} to consumable generic {} of {}",
value, name, parselet
)
);
}
} else if utils::identifier_is_consumable(name) {
} else {
scope.error(
arg.0,
format!(
"Cannot assign non-consumable {} to consumable generic {} of {}",
arg.1, name, parselet
)
format!("Expecting argument for generic '{}'", name),
);
}

Expand Down Expand Up @@ -275,10 +280,7 @@ impl ImlValue {

if without_arguments {
parselet.signature.len() == 0
|| parselet
.signature
.iter()
.all(|arg| !matches!(arg.1, Self::Unset))
|| parselet.signature.iter().all(|arg| arg.1.is_some())
} else {
true
}
Expand Down Expand Up @@ -324,7 +326,6 @@ impl ImlValue {
let start = ops.len();

match self {
ImlValue::Unset => return,
ImlValue::Unresolved(value) => {
return value.borrow().compile(program, current, offset, call, ops)
}
Expand Down Expand Up @@ -352,6 +353,8 @@ impl ImlValue {
}
ImlValue::Generic { name, .. } => {
return current.0.borrow().generics[name]
.as_ref()
.unwrap()
.compile(program, current, offset, call, ops)
}
ImlValue::SelfValue | ImlValue::SelfToken | ImlValue::Parselet(_) => {}
Expand Down Expand Up @@ -406,7 +409,6 @@ impl ImlValue {
impl std::fmt::Display for ImlValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Unset => write!(f, "unset"),
Self::Unresolved(value) => value.borrow().fmt(f),
Self::SelfValue => write!(f, "self"),
Self::SelfToken => write!(f, "Self"),
Expand Down Expand Up @@ -439,7 +441,15 @@ impl std::fmt::Display for ImlValue {
let mut first = true;

for arg in args {
write!(f, "{}{}", if !first { ", " } else { "" }, arg.1)?;
write!(
f,
"{}{}",
if !first { ", " } else { "" },
arg.1
.as_ref()
.map(|v| v.to_string())
.unwrap_or("None".to_string())
)?;
first = false;
}

Expand All @@ -449,7 +459,11 @@ impl std::fmt::Display for ImlValue {
"{}{}:{}",
if !first { ", " } else { "" },
narg,
nargs[narg].1
nargs[narg]
.1
.as_ref()
.map(|v| v.to_string())
.unwrap_or("None".to_string())
)?;
first = false;
}
Expand All @@ -463,7 +477,6 @@ impl std::fmt::Display for ImlValue {
impl std::hash::Hash for ImlValue {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
match self {
Self::Unset => state.write_u8('u' as u8),
Self::Unresolved(value) => value.borrow().hash(state),
Self::VoidToken => state.write_u8('V' as u8),
Self::Value(value) => {
Expand All @@ -480,7 +493,7 @@ impl std::hash::Hash for ImlValue {
consumable.hash(state);
}
*/
other => unreachable!("{} is unhashable", other),
other => unreachable!("{:?} is unhashable", other),
}
}
}
Expand Down

0 comments on commit 0c0fc44

Please sign in to comment.