cl-interpret: References, part 3
MODS ARE ASLEEP POST FAT BEAGLE
This commit is contained in:
parent
9b460afed4
commit
fa5244dcf9
@ -1,5 +1,5 @@
|
|||||||
//! Utils for [Path]
|
//! Utils for [Path]
|
||||||
use crate::{ast::Path, PathPart, Sym};
|
use crate::{PathPart, Sym, ast::Path};
|
||||||
|
|
||||||
impl Path {
|
impl Path {
|
||||||
/// Appends a [PathPart] to this [Path]
|
/// Appends a [PathPart] to this [Path]
|
||||||
@ -21,6 +21,13 @@ impl Path {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_sym(&self) -> Option<Sym> {
|
||||||
|
match self.parts.as_slice() {
|
||||||
|
[PathPart::Ident(name)] => Some(*name),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks whether this path ends in the given [Sym]
|
/// Checks whether this path ends in the given [Sym]
|
||||||
pub fn ends_with(&self, name: &str) -> bool {
|
pub fn ends_with(&self, name: &str) -> bool {
|
||||||
match self.parts.as_slice() {
|
match self.parts.as_slice() {
|
||||||
|
@ -408,7 +408,14 @@ mod assignment {
|
|||||||
ExprKind::Member(member) => addrof_member(env, member),
|
ExprKind::Member(member) => addrof_member(env, member),
|
||||||
ExprKind::Index(index) => addrof_index(env, index),
|
ExprKind::Index(index) => addrof_index(env, index),
|
||||||
ExprKind::Group(Group { expr }) => addrof(env, expr),
|
ExprKind::Group(Group { expr }) => addrof(env, expr),
|
||||||
ExprKind::AddrOf(AddrOf { mutable: Mutability::Mut, expr }) => addrof(env, expr),
|
ExprKind::Unary(Unary { kind: UnaryKind::Deref, tail }) => match *addrof(env, tail)? {
|
||||||
|
ConValue::Ref(place) => env
|
||||||
|
.get_id_mut(place)
|
||||||
|
.ok_or(Error::NotIndexable)?
|
||||||
|
.as_mut()
|
||||||
|
.ok_or(Error::NotAssignable),
|
||||||
|
_ => Err(Error::TypeError),
|
||||||
|
},
|
||||||
_ => Err(Error::TypeError),
|
_ => Err(Error::TypeError),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -432,13 +439,9 @@ mod assignment {
|
|||||||
member: &Member,
|
member: &Member,
|
||||||
) -> IResult<&'e mut ConValue> {
|
) -> IResult<&'e mut ConValue> {
|
||||||
let Member { head, kind } = member;
|
let Member { head, kind } = member;
|
||||||
let ExprKind::Path(path) = &head.kind else {
|
|
||||||
return Err(Error::TypeError);
|
let head = addrof(env, head)?;
|
||||||
};
|
project_memberkind(head, kind)
|
||||||
let slot = addrof_path(env, &path.parts)?
|
|
||||||
.as_mut()
|
|
||||||
.ok_or(Error::NotAssignable)?;
|
|
||||||
project_memberkind(slot, kind)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn addrof_index<'e>(env: &'e mut Environment, index: &Index) -> IResult<&'e mut ConValue> {
|
fn addrof_index<'e>(env: &'e mut Environment, index: &Index) -> IResult<&'e mut ConValue> {
|
||||||
@ -447,6 +450,7 @@ mod assignment {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|index| index.interpret(env))
|
.map(|index| index.interpret(env))
|
||||||
.collect::<IResult<Vec<_>>>()?;
|
.collect::<IResult<Vec<_>>>()?;
|
||||||
|
|
||||||
let mut head = addrof(env, head)?;
|
let mut head = addrof(env, head)?;
|
||||||
for index in indices {
|
for index in indices {
|
||||||
head = project_index(head, &index)?;
|
head = project_index(head, &index)?;
|
||||||
@ -657,7 +661,7 @@ fn cast(env: &Environment, value: ConValue, ty: Sym) -> IResult<ConValue> {
|
|||||||
env,
|
env,
|
||||||
env.get_id(v).cloned().ok_or(Error::StackUnderflow)?,
|
env.get_id(v).cloned().ok_or(Error::StackUnderflow)?,
|
||||||
ty,
|
ty,
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
// TODO: This, better
|
// TODO: This, better
|
||||||
ConValue::Float(_) if ty.starts_with('f') => return Ok(value),
|
ConValue::Float(_) if ty.starts_with('f') => return Ok(value),
|
||||||
@ -702,11 +706,19 @@ impl Interpret for Cast {
|
|||||||
impl Interpret for Member {
|
impl Interpret for Member {
|
||||||
fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
|
fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
|
||||||
let Member { head, kind } = self;
|
let Member { head, kind } = self;
|
||||||
if let ExprKind::Path(_) = &head.kind {
|
// Attempt member access projection (fast path)
|
||||||
return assignment::addrof_member(env, self).cloned();
|
if let Ok(member) = assignment::addrof_member(env, self) {
|
||||||
|
return Ok(member.clone());
|
||||||
}
|
}
|
||||||
let head = head.interpret(env)?;
|
// Evaluate if this can be Self'd
|
||||||
match (head, kind) {
|
let value = match (&head.kind, kind) {
|
||||||
|
(ExprKind::Path(p), MemberKind::Call(..)) => {
|
||||||
|
p.as_sym().map(|name| Ok(ConValue::Ref(env.id_of(name)?))) // "borrow" it
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
// Perform alternate member access
|
||||||
|
match (value.unwrap_or_else(|| head.interpret(env))?, kind) {
|
||||||
(ConValue::Struct(parts), MemberKind::Call(name, args))
|
(ConValue::Struct(parts), MemberKind::Call(name, args))
|
||||||
if parts.1.contains_key(name) =>
|
if parts.1.contains_key(name) =>
|
||||||
{
|
{
|
||||||
|
69
sample-code/unionfind.cl
Normal file
69
sample-code/unionfind.cl
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
//! Disjoint Set Forest implementation of the Union Find algorithm
|
||||||
|
|
||||||
|
// enum TreeNode {
|
||||||
|
// Empty,
|
||||||
|
// Filled { parent: usize, rank: usize }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// TODO: Namespace based on type of first argument
|
||||||
|
|
||||||
|
fn makeset(f, x) {
|
||||||
|
match (*f)[x] {
|
||||||
|
() => (*f)[x] = Filled { parent: x, rank: 0 },
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn union(f, a, b) {
|
||||||
|
let (a, b) = (find(f, a), find(f, b));
|
||||||
|
if a == b { return; }
|
||||||
|
match ((*f)[a], (*f)[b]) {
|
||||||
|
(Filled {parent: _, rank: r_a}, Filled {parent: _, rank: r_b}) => {
|
||||||
|
if r_a < r_b {
|
||||||
|
union(f, b, a)
|
||||||
|
} else {
|
||||||
|
(*f)[b].parent = a;
|
||||||
|
(*f)[a].rank += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find(f, x) {
|
||||||
|
match (*f)[x] {
|
||||||
|
Filled { parent, rank } => if parent == x {
|
||||||
|
x
|
||||||
|
} else {
|
||||||
|
let parent = find(f, parent);
|
||||||
|
(*f)[x].parent = parent;
|
||||||
|
parent
|
||||||
|
},
|
||||||
|
() => x,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show(f) {
|
||||||
|
for node in 0..(len((*f))) {
|
||||||
|
match (*f)[node] {
|
||||||
|
Filled { parent, rank } => println(node, ": { parent: ", parent, ", rank: ", rank, " }"),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test(f) {
|
||||||
|
"Union Find on Disjoint Set Forest".println()
|
||||||
|
for i in 0..10 { makeset(f, i) }
|
||||||
|
for i in 10..20 { makeset(f, i) }
|
||||||
|
show(f)
|
||||||
|
println()
|
||||||
|
|
||||||
|
for i in 1..10 { union(f, i*2-1, i*2) }
|
||||||
|
for i in 5..10 { union(f, i*2+1, i*2) }
|
||||||
|
show(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let f = [();20]
|
||||||
|
f.test()
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user