Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reworks on ImlValue #134

Merged
merged 1 commit into from
Feb 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Replace ImlValue::Unset by Option<ImlValue>
  • Loading branch information
phorward committed Feb 3, 2024
commit 0c0fc4417166764c49d491a94c6974f20cfb9483
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
Loading