// the argument value can be: int, double, String, DataElement public static void check(Object argument, DataType parameter_datatype, AccessType parameter_accesstype) { // check if it is permitted to pass this variable if (argument is DataElement) { DataElement e = (DataElement)argument; DataType et = e.datatype; if (et != parameter_datatype && parameter_datatype != DataType.Unspecified) { throw new AssemblerException("Using variable of wrong type for call: " + e.name); } } // check in which cases a constant integer value is permitted else if (argument is int) { int c = (int)argument; if (parameter_accesstype == AccessType.ReadMany && parameter_datatype == DataType.I8) { throw new AssemblerException("Using constant value as parameter where a string value or variable reference is required"); } if (parameter_accesstype != AccessType.Read) { throw new AssemblerException("Using constant value as parameter where a variable reference is required"); } switch (parameter_datatype) { case DataType.I8: if (c < -128 || c > 127) { throw new AssemblerException("Constant value " + c + "+ out of range of I8"); } break; case DataType.I16: case DataType.VMThread: if (c < -32768 || c > 32767) { throw new AssemblerException("Constant value " + c + "+ out of range of I16"); } break; case DataType.I32: break; // must be implicitly in range default: throw new AssemblerException("Constant value " + c + " does not fit the parameter type " + parameter_datatype); } } // check in which cases a constant float value is permitted else if (argument is double) { if (parameter_datatype != DataType.F && parameter_datatype != DataType.Unspecified) { throw new AssemblerException("Can not use float literal '" + argument + "' for this parameter type"); } if (parameter_accesstype != AccessType.Read) { throw new AssemblerException("Can not use float literal '" + argument + "' for output parameter"); } } // check in which cases a string literal is permitted else if (argument is String) { if (parameter_datatype != DataType.I8) { throw new AssemblerException("Can not use string literal '" + argument + "' for this parameter type"); } if (parameter_accesstype != AccessType.Read && parameter_accesstype != AccessType.ReadMany) { throw new AssemblerException("Can not use string literal '" + argument + "' for output parameter"); } } }
// decodes a parameter and adds it to bytecode stream. // return either DataElement, int, double, or String (for type checking) private Object DecodeAndAddParameter(DataArea locals, String p) { // this must be a label address difference if ((!p.StartsWith("'")) && p.Contains(':')) { currentobject.AddLabelDifference(p); return(999999999); // only compatible with 32bit numbers } // this must be a variable else if ((p[0] >= 'A' && p[0] <= 'Z') || p[0] == '_') { // check if have offset suffix int offset = 0; int plusidx = p.IndexOf('+'); if (plusidx >= 0) { if (Int32.TryParse(p.Substring(plusidx + 1), NumberStyles.Integer, CultureInfo.InvariantCulture, out offset)) { p = p.Substring(0, plusidx); } } DataElement e = null; bool local = true; if (locals != null) { e = locals.Get(p); } if (e == null) { e = globals.Get(p); local = false; } if (e == null) { throw new AssemblerException("Unknown identifier " + p); } currentobject.AddVariableReference(e.position + offset, local); return(e); } // this must be a constant numeric value else if ((p[0] >= '0' && p[0] <= '9') || p[0] == '-') { Int32 c; double d; if (Int32.TryParse(p, NumberStyles.Integer, CultureInfo.InvariantCulture, out c)) { currentobject.AddConstant(c); return(c); } if (double.TryParse(p, NumberStyles.Float, CultureInfo.InvariantCulture, out d)) { currentobject.AddFloatConstant(d); return(d); } throw new AssemblerException("Can not decode number: " + p); } // this must be a string literal else if (p[0] == '\'') { String l = p.Substring(1, p.Length - 2); currentobject.AddStringLiteral(l); return(l); } else { throw new AssemblerException("Invalid parameter value"); } }