1
0
Fork 0

add a props.condition(property) command that evaluates a property branch

as <condition> according to the rules set out in $FG_ROOT/Docs/README.condition
This commit is contained in:
mfranz 2007-03-18 13:57:32 +00:00
parent 5f7104ac8a
commit 0b4e6f934e

View file

@ -84,7 +84,7 @@ Node._setChildren = func {
if(typeof(val) == "scalar") { subnode.setValue(val); } if(typeof(val) == "scalar") { subnode.setValue(val); }
elsif(typeof(val) == "hash") { subnode.setValues(val); } elsif(typeof(val) == "hash") { subnode.setValues(val); }
elsif(typeof(val) == "vector") { elsif(typeof(val) == "vector") {
for(i=0; i<size(val); i=i+1) { for(i=0; i<size(val); i+=1) {
iname = name ~ "[" ~ i ~ "]"; iname = name ~ "[" ~ i ~ "]";
me._setChildren(iname, val[i]); me._setChildren(iname, val[i]);
} }
@ -96,7 +96,7 @@ Node._setChildren = func {
# Node object to the console. Try binding "props.dump(props.globals)" # Node object to the console. Try binding "props.dump(props.globals)"
# to a key for a fun hack. # to a key for a fun hack.
# #
dump = func { var dump = func {
if(size(arg) == 1) { prefix = ""; node = arg[0]; } if(size(arg) == 1) { prefix = ""; node = arg[0]; }
else { prefix = arg[0]; node = arg[1]; } else { prefix = arg[0]; node = arg[1]; }
@ -121,7 +121,7 @@ dump = func {
# Recursively copy property branch from source Node to # Recursively copy property branch from source Node to
# destination Node. Doesn't copy aliases. # destination Node. Doesn't copy aliases.
# #
copy = func(src, dest) { var copy = func(src, dest) {
foreach(c; src.getChildren()) { foreach(c; src.getChildren()) {
name = c.getName() ~ "[" ~ c.getIndex() ~ "]"; name = c.getName() ~ "[" ~ c.getIndex() ~ "]";
copy(src.getNode(name), dest.getNode(name, 1)); copy(src.getNode(name), dest.getNode(name, 1));
@ -139,14 +139,14 @@ copy = func(src, dest) {
# Utility. Turns any ghosts it finds (either solo, or in an # Utility. Turns any ghosts it finds (either solo, or in an
# array) into Node objects. # array) into Node objects.
# #
wrap = func { var wrap = func {
argtype = typeof(arg[0]); argtype = typeof(arg[0]);
if(argtype == "ghost") { if(argtype == "ghost") {
return wrapNode(arg[0]); return wrapNode(arg[0]);
} elsif(argtype == "vector") { } elsif(argtype == "vector") {
v = arg[0]; v = arg[0];
n = size(v); n = size(v);
for(i=0; i<n; i=i+1) { v[i] = wrapNode(v[i]); } for(i=0; i<n; i+=1) { v[i] = wrapNode(v[i]); }
return v; return v;
} }
return arg[0]; return arg[0];
@ -157,7 +157,7 @@ wrap = func {
# Node object and its _g (ghost) field set to the specified object. # Node object and its _g (ghost) field set to the specified object.
# Nasal's literal syntax can be pleasingly terse. I like that. :) # Nasal's literal syntax can be pleasingly terse. I like that. :)
# #
wrapNode = func { { parents : [Node], _g : arg[0] } } var wrapNode = func { { parents : [Node], _g : arg[0] } }
## ##
# Global property tree. Set once at initialization. Is that OK? # Global property tree. Set once at initialization. Is that OK?
@ -172,7 +172,7 @@ props.globals = wrapNode(_globals());
# path under each node of that name to set (e.g. "throttle"), arg[2] # path under each node of that name to set (e.g. "throttle"), arg[2]
# is the value. # is the value.
# #
setAll = func { var setAll = func {
node = props.globals.getNode(arg[0]); node = props.globals.getNode(arg[0]);
if(node == nil) { return; } if(node == nil) { return; }
name = node.getName(); name = node.getName();
@ -183,3 +183,71 @@ setAll = func {
if(c.getName() == name) { if(c.getName() == name) {
c.getNode(arg[1], 1).setValue(arg[2]); }} c.getNode(arg[1], 1).setValue(arg[2]); }}
} }
##
# Evaluates a <condition> property branch according to the rules
# set out in $FG_ROOT/Docs/README.condition.
#
var condition = func(p) {
if(!isa(p, props.Node)) { p = props.globals.getNode(p); }
return _cond_and(p)
}
var _cond_and = func(p) {
foreach(var c; p.getChildren()) {
if(!_cond(c)) { return 0; }
}
return 1;
}
var _cond_or = func(p) {
foreach(var c; p.getChildren()) {
if(_cond(c)) { return 1; }
}
return 0;
}
var _cond = func(p) {
var n = p.getName();
if(n == "not") { return !_cond_and(p); }
if(n == "and") { return _cond_and(p); }
if(n == "or") { return _cond_or(p); }
if(n == "equals") { return _cond_cmp(p, "EQ"); }
if(n == "not-equals") { return !_cond_cmp(p, "EQ"); }
if(n == "less-than") { return _cond_cmp(p, "LT"); }
if(n == "greater-than") { return _cond_cmp(p, "GT"); }
if(n == "less-than-equals") { return !_cond_cmp(p, "GT"); }
if(n == "greater-than-equals") { return !_cond_cmp(p, "LT"); }
if(n == "property") { return getprop(p.getValue()); }
printlog("alert", "condition: invalid operator ", n);
dump(p);
return nil;
}
var _cond_cmp = func(p, op) {
var left = p.getChild("property", 0, 0);
if(left != nil) { left = getprop(left.getValue()); }
else {
printlog("alert", "condition: no left value");
dump(p);
return nil;
}
var right = p.getChild("property", 1, 0);
if(right != nil) { right = getprop(right.getValue()); }
else {
right = p.getChild("value", 0, 0);
if(right != nil) { right = right.getValue(); }
else {
printlog("alert", "condition: no right value");
dump(p);
return nil;
}
}
if(left == nil or right == nil) {
printlog("alert", "condition: comparing with nil");
dump(p);
return nil;
}
return op == "LT" ? left < right : op == "GT" ? left > right : left == right;
}