public MinceObject Index() { MinceObject result = Add(); while (interpreter.currentToken.type == "L_SQUARE_BRACKET") { if (result.GetType() != typeof(MinceArray)) { throw new InterpreterException(interpreter.currentToken, "Can only apply an index to an Array, not a " + result.GetType().Name); } interpreter.Eat(); MinceObject index = Evaluate(); if (index.GetType() != typeof(MinceNumber)) { throw new InterpreterException(interpreter.currentToken, "Index must be a number! Not a " + index.GetType().Name); } interpreter.Eat("R_SQUARE_BRACKET"); result = ((MinceArray)result).get((MinceNumber)index); continue; } return(result); }
public override MinceObject Evaluate(Interpreter interpreter) { interpreter.Eat(); MinceObject returnValue = interpreter.evaluation.Evaluate(); interpreter.Eat("SEMICOLON"); return(returnValue); }
public MinceObject Exponent() { MinceObject result = Members(); while (interpreter.currentToken.type == "EXPONENT") { interpreter.Eat(); result = result.Exponent(Members()); } return(result); }
public override MinceObject Evaluate(Interpreter interpreter) { interpreter.Eat(); string name = interpreter.Eat("IDENTIFIER").ToString(); interpreter.Eat("EQUALS"); MinceObject value = interpreter.evaluation.Evaluate(); Variable v = new Variable(name, value, false); interpreter.variables.variables.Add(v); interpreter.Eat("SEMICOLON"); return(new MinceNull()); }
public MinceObject Compare() { MinceObject result = Index(); while ( new List <string>() { "IS_EQUAL", "NOT_EQUAL", "GREATER_THAN", "LESS_THAN", "GREATER_OR_EQUAL", "LESS_OR_EQUAL" }.Contains(interpreter.currentToken.type)) { switch (interpreter.currentToken.type) { case "IS_EQUAL": interpreter.Eat(); result = result.EqualTo(Add()); break; case "NOT_EQUAL": interpreter.Eat(); result = result.NotEqualTo(Add()); break; case "GREATER_THAN": interpreter.Eat(); result = result.GreaterThan(Add()); break; case "LESS_THAN": interpreter.Eat(); result = result.LessThan(Add()); break; case "GREATER_OR_EQUAL": interpreter.Eat(); result = result.GreaterOrEqual(Add()); break; case "LESS_OR_EQUAL": interpreter.Eat(); result = result.LessOrEqual(Add()); break; } } return(result); }
public MinceObject AndOr() { MinceObject result = Compare(); while (interpreter.currentToken.type == "AND" || interpreter.currentToken.type == "OR") { switch (interpreter.currentToken.type) { case "AND": interpreter.Eat(); result = result.And((MinceBool)Compare()); break; case "OR": interpreter.Eat(); result = result.Or((MinceBool)Compare()); break; } } return(result); }
public MinceObject Multiply() { MinceObject result = Exponent(); while (interpreter.currentToken.type == "MULTIPLY" || interpreter.currentToken.type == "DIVIDE") { switch (interpreter.currentToken.type) { case "MULTIPLY": interpreter.Eat(); result = result.Multiply(Exponent()); break; case "DIVIDE": interpreter.Eat(); result = result.Divide(Exponent()); break; } } return(result); }
public MinceObject Add() { MinceObject result = Multiply(); while (interpreter.currentToken.type == "PLUS" || interpreter.currentToken.type == "MINUS") { switch (interpreter.currentToken.type) { case "PLUS": interpreter.Eat(); result = result.Plus(Multiply()); break; case "MINUS": interpreter.Eat(); result = result.Minus(Multiply()); break; } } return(result); }
public MinceObject NewClass(MinceObject original, MinceObject[] args) { MinceObject obj = original.clone(); foreach (var member in obj.members) { if (member.GetType() == typeof(Property)) { Property prop = (Property)member; prop.getFunc.parent = obj; if (prop.setFunc != null) { prop.setFunc.parent = obj; } prop.Init(); } else if (member.GetValue().GetType() == typeof(MinceUserFunction)) { ((MinceUserFunction)member.GetValue()).parent = obj; } } foreach (var method in obj.members) { if (method.GetType() == typeof(Variable) && method.GetValue().GetType() == typeof(MinceUserFunction) && method.name == "new") { ((MinceUserFunction)method.GetValue()).call(args); obj.members.Remove(method); break; } } return(obj); }
public void SetParent(MinceObject parent) { this.parent = parent; variables.variables.Add(new Variable("this", this.parent, true, depth)); }
public void LoadAssemblies() { Type[] classes = Assembly.GetExecutingAssembly().GetTypes().Where(t => String.Equals(t.Namespace, "Mince.Types", StringComparison.Ordinal)).ToArray(); foreach (Type c in classes) { foreach (Attribute attr in c.GetCustomAttributes(true)) { if (attr.GetType() == typeof(StaticClass)) { var st = (StaticClass)attr; MinceObject value = (MinceObject)Activator.CreateInstance(c); Variable v = new Variable(st.name, value); variables.variables.Add(v); break; } else if (attr.GetType() == typeof(Instantiatable)) { if (c.GetConstructor(new Type[0]) == null) { Console.WriteLine("Could not load " + c + ". All instantiatable types must have a parameterless constructor."); } Func <MinceObject[], MinceObject> func = args => (MinceObject)Activator.CreateInstance(c, args, new object[0]); string name = ((Instantiatable)attr).name; types.Add(name, func); break; } } } foreach (string file in dlls) { Assembly assembly; try { assembly = Assembly.LoadFile(file); } catch { Console.WriteLine("Couldn't load lib/" + file.Substring(file.LastIndexOf("\\") + 1)); continue; } foreach (Type c in assembly.GetTypes()) { foreach (Attribute attr in c.GetCustomAttributes(true)) { if (attr.GetType() == typeof(StaticClass)) { var st = (StaticClass)attr; MinceObject value = (MinceObject)Activator.CreateInstance(c); Variable v = new Variable(st.name, value); variables.variables.Add(v); break; } else if (attr.GetType() == typeof(Instantiatable)) { Func <MinceObject[], MinceObject> func = args => (MinceObject)Activator.CreateInstance(c, args, new object[0]); string name = ((Instantiatable)attr).name; types.Add(name, func); break; } } } } }
public override MinceObject Evaluate(Interpreter interpreter) { string identifier = interpreter.Eat().ToString(); if (interpreter.variables.Exists(identifier)) { interpreter.pointer--; VariableTree tree = Identifier.GetTree(interpreter); if (!tree.lastWasFunc) { if (interpreter.currentToken.type == "EQUALS") { if (tree.lastVariable.isReadOnly) { throw new InterpreterException(interpreter.previousToken, "'" + tree.lastVariable.name + "' is readonly!"); } interpreter.Eat(); MinceObject result = interpreter.evaluation.Evaluate(); tree.lastVariable.SetValue(result); } else if (interpreter.currentToken.type == "PLUS" && interpreter.tokens[interpreter.pointer + 1].type == "PLUS") { if (tree.lastVariable.GetValue().GetType() != typeof(MinceNumber)) { throw new InterpreterException(interpreter.previousToken, "Can only increment a MinceNumber, not a " + tree.lastVariable.GetValue().GetType().Name); } interpreter.Eat(); interpreter.Eat(); ((MinceNumber)tree.lastVariable.GetValue()).inc(); } else if (interpreter.currentToken.type == "MINUS" && interpreter.tokens[interpreter.pointer + 1].type == "MINUS") { if (tree.lastVariable.GetValue().GetType() != typeof(MinceNumber)) { throw new InterpreterException(interpreter.previousToken, "Can only increment a MinceNumber, not a " + tree.lastVariable.GetValue().GetType().Name); } interpreter.Eat(); interpreter.Eat(); MinceNumber num = (MinceNumber)tree.lastVariable.GetValue(); tree.lastVariable.SetValue(num.Minus(new MinceNumber(1))); } } interpreter.Eat("SEMICOLON"); } else { Variable variable = new Variable(); variable.name = identifier; variable.depth = interpreter.depth; interpreter.Eat("EQUALS"); MinceObject value = interpreter.evaluation.Evaluate(); variable.SetValue(value); interpreter.variables.variables.Add(variable); interpreter.Eat("SEMICOLON"); } return(new MinceNull()); }
public static VariableTree GetTree(Interpreter interpreter) { VariableTree tree = new VariableTree(); string identifier = interpreter.Eat().ToString(); if (interpreter.variables.Exists(identifier)) { Variable variable = interpreter.variables.Get(identifier); MinceObject value = variable.GetValue(); bool lastWasFunc = value.GetType() == typeof(MinceFunction) || value.GetType() == typeof(MinceUserFunction); tree.Add(variable); while (true) { if (interpreter.currentToken.type == "L_BRACKET") { interpreter.Eat(); MinceObject[] args = interpreter.GetParameters(); interpreter.Eat("R_BRACKET"); if (value.GetType() == typeof(MinceUserFunction)) { value = (value as MinceUserFunction).call(args); } else if (value.GetType() == typeof(MinceFunction)) { value = (value as MinceFunction).Call(args); } else { throw new InterpreterException(interpreter.currentToken, variable.name + " is not a function! It is a " + value.GetType().Name); } lastWasFunc = true; continue; } if (interpreter.currentToken.type == "L_SQUARE_BRACKET") { if (value.GetType() != typeof(MinceArray)) { throw new InterpreterException(interpreter.currentToken, "Can only apply an index to an Array, not a " + value.GetType().Name); } interpreter.Eat(); MinceObject index = interpreter.evaluation.Evaluate(); if (index.GetType() != typeof(MinceNumber)) { throw new InterpreterException(interpreter.currentToken, "Index must be a number! Not a " + index.GetType().Name); } interpreter.Eat("R_SQUARE_BRACKET"); value = ((MinceArray)value).get((MinceNumber)index); continue; } if (interpreter.currentToken.type == "DOT") { interpreter.Eat(); string name = interpreter.Eat("IDENTIFIER").ToString(); if (value.MemberExists(name)) { variable = value.GetMember(name); tree.Add(variable); if (variable.isPrivate) { if (interpreter.parent == null || !object.ReferenceEquals(value, interpreter.parent)) { throw new InterpreterException(interpreter.previousToken, "'" + variable.name + "' is private!"); } } value = variable.GetValue(); } else if (value.GetType() == typeof(MinceDynamic)) { Variable v = new Variable(name, new MinceDynamic(), false, -1); value.members.Add(v); variable = v; tree.Add(variable); } else { throw new InterpreterException(interpreter.previousToken, "'" + variable.name + "' (" + variable.GetValue().GetType().Name + ") does not contain member '" + name + "'"); } lastWasFunc = false; } else { break; } } tree.lastWasFunc = false; return(tree); } else { throw new InterpreterException(interpreter.previousToken, "Variable '" + identifier + "' does not exist!"); } }
public override void SetValue(MinceObject assignment) { property.SetValue(instance, assignment); }
public MinceObject Factor() { if (new List <string>() { "NUMBER", "STRING", "BOOL", "CHAR" }.Contains(interpreter.currentToken.type)) { return((MinceObject)interpreter.Eat()); } else if (interpreter.currentToken.type == "L_BRACKET") { interpreter.Eat("L_BRACKET"); MinceObject result = Evaluate(); interpreter.Eat("R_BRACKET"); return(result); } else if (interpreter.currentToken.type == "IDENTIFIER") { string name = interpreter.Eat().ToString(); if (interpreter.variables.Exists(name)) { var result = interpreter.variables.Get(name).GetValue(); if (result.GetType() == typeof(MinceUserFunction)) { if (interpreter.currentToken.type == "L_BRACKET") { var func = result as MinceUserFunction; interpreter.Eat(); MinceObject[] args = interpreter.GetParameters(); interpreter.Eat("R_BRACKET"); return(func.call(args)); } else { return(result); } } else { return(result); } } else { throw new InterpreterException(interpreter.currentToken, "'" + name + "' does not exist in this context"); } } else if (interpreter.currentToken.type == "NEW") { interpreter.Eat(); var func = Interpreter.types[interpreter.Eat("IDENTIFIER").ToString()]; interpreter.Eat("L_BRACKET"); var p = interpreter.GetParameters(); interpreter.Eat("R_BRACKET"); return(func.Invoke(p)); } else if (interpreter.currentToken.type == "NOT") { interpreter.Eat(); return(new MinceBool(!(bool)(this.Evaluate() as MinceBool).value)); } else if (interpreter.currentToken.type == "NULL") { interpreter.Eat(); return(new MinceNull()); } else if (interpreter.currentToken.type == "FUNCTION") { int initialDepth = interpreter.depth; interpreter.Eat(); MinceUserFunction userFunc = new MinceUserFunction(); List <Token> tokens = new List <Token>(); List <string> paramNames = new List <string>(); if (interpreter.currentToken.type == "COLON") { interpreter.Eat(); while (interpreter.currentToken.type == "IDENTIFIER") { string name = interpreter.Eat().ToString(); if (interpreter.variables.Exists(name)) { throw new InterpreterException(interpreter.currentToken, "A variable called '" + name + "' already exists!"); } paramNames.Add(name); if (interpreter.currentToken.type == "L_CURLY_BRACE") { break; } else if (interpreter.currentToken.type == "COMMA") { interpreter.Eat(); } else { throw new InterpreterException(interpreter.currentToken, "Expected ',' or '{' after parameter name"); } } } interpreter.Eat("L_CURLY_BRACE"); interpreter.depth++; tokens.Add(new Token(0, 0, "L_CURLY_BRACE")); tokens = tokens.Concat(interpreter.SkipBlock()).ToList(); userFunc.value = tokens; userFunc.variableNames = paramNames; return(userFunc); } else if (interpreter.currentToken.type == "L_SQUARE_BRACKET") { MinceArray ar = new MinceArray(new MinceObject[0]); interpreter.Eat(); while (interpreter.currentToken.type != "R_SQUARE_BRACKET") { ar.add(Evaluate()); if (interpreter.currentToken.type != "R_SQUARE_BRACKET") { interpreter.Eat("COMMA"); } } interpreter.Eat(); return(ar); } else if (interpreter.currentToken.type == "L_CURLY_BRACE") { MinceDynamic d = new MinceDynamic(); interpreter.Eat(); while (interpreter.currentToken.type == "IDENTIFIER") { string name = interpreter.Eat().ToString(); interpreter.Eat("EQUALS"); MinceObject value = Evaluate(); Variable v = new Variable(name, value, true); d.members.Add(v); if (interpreter.currentToken.type != "COMMA") { break; } interpreter.Eat(); } interpreter.Eat("R_CURLY_BRACE"); return(d); } else if (interpreter.currentToken.type == "EOF") { return(new MinceNull()); } throw new InterpreterException(interpreter.currentToken, "Unexpected token " + interpreter.currentToken.ToString() + " found when looking for a factor at token #" + interpreter.pointer); }
public MinceObject Members() { MinceObject result = Factor(); while (interpreter.currentToken.type == "DOT") { interpreter.Eat(); string memberName = interpreter.Eat("IDENTIFIER").ToString(); if (result.MemberExists(memberName)) { if (result.GetMember(memberName).isPrivate) { if (interpreter.parent == null || !object.ReferenceEquals(result, interpreter.parent)) { throw new InterpreterException(interpreter.currentToken, "'" + result.GetMember(memberName).name + "' is private!"); } } if (interpreter.currentToken.type == "L_BRACKET") { var member = result.GetMember(memberName).GetValue(); if (member.GetType() == typeof(MinceUserFunction)) { var func = member as MinceUserFunction; interpreter.Eat(); MinceObject[] args = interpreter.GetParameters(); interpreter.Eat("R_BRACKET"); result = func.call(args); } else if (member.GetType() == typeof(MinceFunction)) { interpreter.Eat("L_BRACKET"); MinceObject[] p = interpreter.GetParameters(); result = (result.GetMember(memberName).GetValue() as MinceFunction).Call(p); interpreter.Eat("R_BRACKET"); } else { throw new InterpreterException(interpreter.currentToken, "You can only call functions, not " + member.GetType()); } } else { result = result.GetMember(memberName).GetValue(); } } else { throw new InterpreterException(interpreter.currentToken, "'" + memberName + "' is inaccessible."); } } return(result); }