use of com.laytonsmith.core.constructs.CFunction in project CommandHelper by EngineHub.
the class OptimizationUtilities method optimize0.
private static String optimize0(ParseTree node) {
if (node.getData() instanceof CFunction) {
StringBuilder b = new StringBuilder();
boolean first = true;
b.append(((CFunction) node.getData()).val()).append("(");
for (ParseTree child : node.getChildren()) {
if (!first) {
b.append(",");
}
first = false;
b.append(optimize0(child));
}
b.append(")");
return b.toString();
} else if (node.getData() instanceof CString) {
// strings
return new StringBuilder().append("'").append(node.getData().val().replaceAll("\t", "\\t").replaceAll("\n", "\\n").replace("\\", "\\\\").replace("'", "\\'")).append("'").toString();
} else if (node.getData() instanceof IVariable) {
return ((IVariable) node.getData()).getVariableName();
} else if (node.getData() instanceof Variable) {
return ((Variable) node.getData()).getVariableName();
} else if (node.getData() instanceof CSlice) {
return node.getData().val();
} else if (node.getData() instanceof CArray) {
// It's a hardcoded array. This only happens in the course of optimization, if
// the optimizer adds a new array. We still need to handle it appropriately though.
// The values in the array will be constant, guaranteed.
StringBuilder b = new StringBuilder();
b.append("array(");
boolean first = true;
CArray n = (CArray) node.getData();
for (String key : n.stringKeySet()) {
if (!first) {
b.append(",");
}
first = false;
b.append(optimize0(new ParseTree(n.get(key, Target.UNKNOWN), node.getFileOptions())));
}
b.append(")");
return b.toString();
} else {
// static
return node.getData().toString();
}
}
use of com.laytonsmith.core.constructs.CFunction in project CommandHelper by EngineHub.
the class OptimizerObject method optimize01.
/**
* This optimization level removes all the __autoconcat__s (and inadvertently several other constructs as well)
*
* @param tree
* @param compilerEnvironment
* @throws ConfigCompileException
*/
private void optimize01(ParseTree tree, CompilerEnvironment compilerEnvironment) throws ConfigCompileException {
com.laytonsmith.core.functions.Compiler.__autoconcat__ autoconcat = (com.laytonsmith.core.functions.Compiler.__autoconcat__) FunctionList.getFunction("__autoconcat__", Target.UNKNOWN);
if (tree.getData() instanceof CFunction && tree.getData().val().equals("__autoconcat__")) {
ParseTree tempNode = autoconcat.optimizeSpecial(tree.getChildren(), true);
tree.setData(tempNode.getData());
tree.setChildren(tempNode.getChildren());
}
for (int i = 0; i < tree.getChildren().size(); i++) {
ParseTree node = tree.getChildren().get(i);
optimize01(node, compilerEnvironment);
}
}
use of com.laytonsmith.core.constructs.CFunction in project CommandHelper by EngineHub.
the class InstanceofKeyword method process.
@Override
public int process(List<ParseTree> list, int keywordPosition) throws ConfigCompileException {
if (list.get(keywordPosition).getData() instanceof CFunction) {
// It's not a keyword, it's a function
return keywordPosition;
}
if (keywordPosition == 0) {
throw new ConfigCompileException("Expected value to proceed \"instanceof\" keyword, but no identifiers were found.", list.get(keywordPosition).getTarget());
}
if (list.size() <= keywordPosition + 1) {
throw new ConfigCompileException("Expected type to follow \"instanceof\" keyword, but no type was found.", list.get(keywordPosition).getTarget());
}
ParseTree node = new ParseTree(new CFunction(INSTANCEOF, list.get(keywordPosition).getTarget()), list.get(keywordPosition).getFileOptions());
node.addChild(list.get(keywordPosition - 1));
node.addChild(list.get(keywordPosition + 1));
// Overwrite the LHS
list.set(keywordPosition - 1, node);
// Remove the keyword
list.remove(keywordPosition);
// Remove the RHS
list.remove(keywordPosition);
return keywordPosition;
}
use of com.laytonsmith.core.constructs.CFunction in project CommandHelper by EngineHub.
the class ProcKeyword method process.
@Override
public int process(List<ParseTree> list, int keywordPosition) throws ConfigCompileException {
if (list.get(keywordPosition).getData() instanceof CKeyword) {
// It's a lone keyword, so we expect some function to follow, which is the proc name + variables
if (list.get(keywordPosition + 1).getData() instanceof CFunction) {
ParseTree proc = new ParseTree(new CFunction(PROC, list.get(keywordPosition).getTarget()), list.get(keywordPosition).getFileOptions());
proc.addChild(new ParseTree(new CString(list.get(keywordPosition + 1).getData().val(), list.get(keywordPosition + 1).getTarget()), list.get(keywordPosition + 1).getFileOptions()));
// Grab the functions children, and put them on the stack
for (ParseTree child : list.get(keywordPosition + 1).getChildren()) {
proc.addChild(child);
}
if (list.size() > keywordPosition + 2) {
validateCodeBlock(list.get(keywordPosition + 2), "Expected braces to follow proc definition");
proc.addChild(getArgumentOrNull(list.get(keywordPosition + 2)));
} else {
throw new ConfigCompileException("Expected braces to follow proc definition", list.get(keywordPosition + 1).getTarget());
}
// Remove the keyword
list.remove(keywordPosition);
// Remove the function definition
list.remove(keywordPosition);
// Remove the cbrace
list.remove(keywordPosition);
// Add in the new proc definition
list.add(keywordPosition, proc);
} else {
throw new ConfigCompileException("Unexpected use of \"proc\" keyword", list.get(keywordPosition).getTarget());
}
} else if (nodeIsProcFunction(list.get(keywordPosition))) {
// It's the functional usage, possibly followed by a cbrace. If so, pull the cbrace in, and that's it
if (list.size() > keywordPosition + 1) {
if (isValidCodeBlock(list.get(keywordPosition + 1))) {
list.get(keywordPosition).addChild(getArgumentOrNull(list.get(keywordPosition + 1)));
list.remove(keywordPosition + 1);
}
}
} else {
// Random keyword in the middle of nowhere
throw new ConfigCompileException("Unexpected use of \"proc\" keyword", list.get(keywordPosition).getTarget());
}
return keywordPosition;
}
use of com.laytonsmith.core.constructs.CFunction in project CommandHelper by EngineHub.
the class IClosureKeyword method process.
@Override
public int process(List<ParseTree> list, int keywordPosition) throws ConfigCompileException {
try {
if (list.get(keywordPosition).getData() instanceof CFunction) {
// It's a function, so do the old processing
SimpleBlockKeywordFunction.doProcess(this.getKeywordName(), null, true, list, keywordPosition);
// easiest if we do the conversion here.
try {
if (list.get(keywordPosition - 1).getData() instanceof CClassType) {
ParseTree type = list.remove(keywordPosition - 1);
List<ParseTree> children = list.get(keywordPosition - 1).getChildren();
children.add(0, type);
list.get(keywordPosition - 1).setChildren(children);
return keywordPosition - 1;
}
} catch (IndexOutOfBoundsException ex) {
// Ignore, it's not a typed closure
}
return keywordPosition;
} else {
// Else it's standalone, so this should be treated as the closure ClassType
list.set(keywordPosition, new ParseTree(CIClosure.TYPE, list.get(keywordPosition).getFileOptions()));
return keywordPosition;
}
} catch (IndexOutOfBoundsException ex) {
throw new ConfigCompileException("Unexpected \"iclosure\" reference", list.get(keywordPosition).getTarget());
}
}
Aggregations