// This is called at the end of the TopLevelEntity's allocation phase and allocates // ID's to the lambda's code. internal void ResolveVariableOriginsForInnerCode(ParserContext parser, VariableScope scopeFromParent) { this.VariableScope = VariableScope.CreateClosure(scopeFromParent); List <VariableId> argVarIds = new List <VariableId>(); for (int i = 0; i < this.Args.Length; ++i) { if (this.Args[i].Value == "xxxx") { } VariableId varId = this.VariableScope.RegisterVariableForcedReDeclaration( this.ArgTypes[i], this.Args[i].Value, this.Args[i]); argVarIds.Add(varId); } this.ArgVarIds = argVarIds.ToArray(); foreach (Executable ex in this.Code) { ex.ResolveVariableOrigins(parser, this.VariableScope, VariableIdAllocPhase.REGISTER_AND_ALLOC); } this.VariableScope.FinalizeScopeIds(); foreach (Lambda lambda in this.Lambdas) { lambda.ResolveVariableOriginsForInnerCode(parser, this.VariableScope); } }
internal override Expression ResolveTypes(ParserContext parser, TypeResolver typeResolver) { int argCount = this.ArgTypes.Length; this.ResolvedArgTypes = new ResolvedType[argCount]; for (int i = 0; i < argCount; ++i) { ResolvedType argType = typeResolver.ResolveType(this.ArgTypes[i]); this.ResolvedArgTypes[i] = argType; // TODO: this variableId will not always be non-null when the argument in a lambda is used by a // closure of another lambda inside the lambda. I'll have to change my strategy here. Possibly // tracking the VariableId's as another Args field. VariableId variableId = this.VariableScope.GetVarId(this.Args[i]); variableId.ResolvedType = argType; } foreach (Executable ex in this.Code) { ex.ResolveTypes(parser, typeResolver); } // TODO: how do you define the lambda return type in Acrylic? Snoop the nested returns, maybe? ResolvedType returnType = ResolvedType.ANY; this.ResolvedType = ResolvedType.GetFunctionType(returnType, this.ResolvedArgTypes, 0); return(this); }
public VariableNode(StatService statService, string id, StatId?parentId) : base(id, NodeType.Stat, 1) { _statService = statService; Id = new VariableId(id, parentId); _parentId = parentId; }
public Iteration(String iteratorName, VariableId listData, List <Brick> brickList) { this.iteratorName = iteratorName; this.listData = listData; this.brickList = brickList; this.listOfParameter = IteratorStr.GetListofIndexParametters(); }
/// <summary> /// Returns the number of bytes that the variable takes. /// </summary> private byte getVariableBytes(VariableId variableId) { switch (variableId) { case VariableId.TARGET_VCC_ALLOWED_MINIMUM: case VariableId.TARGET_VCC_ALLOWED_MAXIMUM_RANGE: case VariableId.TARGET_VCC_MEASURED_MINIMUM: case VariableId.TARGET_VCC_MEASURED_MAXIMUM: case VariableId.PROGRAMMING_ERROR: case VariableId.LINE_A_IDENTITY: case VariableId.LINE_B_IDENTITY: case VariableId.SLOSCOPE_STATE: case VariableId.SW_MINOR: case VariableId.SW_MAJOR: case VariableId.HW_VER: case VariableId.SCK_DURATION: return(1); case VariableId.FVR_ADC: case VariableId.SLOSCOPE_OUTPUT_STATE: return(2); default: throw new Exception("Unrecognized variabledId " + variableId.ToString()); } }
private unsafe ushort getVariable(VariableId variableId) { byte bytes = getVariableBytes(variableId); ushort value = 0; byte[] array = new byte[bytes]; try { controlTransfer(0xC0, 0x81, 0, (ushort)variableId, array); } catch (Exception e) { throw new Exception("There was an error getting variable " + variableId.ToString() + " from the device.", e); } if (bytes == 1) { // read a single byte fixed(byte *pointer = array) { value = *(byte *)pointer; } } else { // read two bytes fixed(byte *pointer = array) { value = *(ushort *)pointer; } } return(value); }
public bool Exists(VariableId id) { if (!Exists(id.StatId)) { return(false); } return(Stats[id.StatId].TryGetVariable(id) != null); }
public void Remove(VariableId variableId) { if (!Exists(variableId)) { throw new ArgumentOutOfRangeException(nameof(variableId)); } //TODO check if used Stats[variableId.StatId].Variables.Remove(variableId); }
private void setVariable(VariableId variableId, ushort value) { try { controlTransfer(0x40, 0x82, value, (ushort)variableId); } catch (Exception e) { throw new Exception("There was an error setting variable " + variableId.ToString() + " on the device.", e); } }
public IEnumerable <string> AddOrUpdate(VariableId id, double value = 0) { var stat = Stats[id.StatId]; if (stat.TryGetVariable(id) != null) { _cache.Clear(); } stat.AddOrUpdateVariable(id, value); return(System.Array.Empty <string>()); }
internal override void ResolveTypes(ParserContext parser, TypeResolver typeResolver) { this.Value = this.Value.ResolveTypes(parser, typeResolver); if (this.type == AssignmentType.TYPED_VARIABLE_DECLARATION) { VariableId varId = this.TargetAsVariable.VarId; AType variableType = varId.Type; varId.ResolvedType = typeResolver.ResolveType(varId.Type); } else if (this.type == AssignmentType.VARIABLE && this.CompilationScope.IsCrayon) { VariableId varId = this.TargetAsVariable.VarId; if (varId.ResolvedType == null) { varId.ResolvedType = parser.TypeContext.ANY; } } this.Target = this.Target.ResolveTypes(parser, typeResolver); // These are special cases that are valid: // list *= num, // string *= num, // string += any non-null value ResolvedTypeCategory leftCategory = this.Target.ResolvedType.Category; ResolvedTypeCategory rightCategory = this.Value.ResolvedType.Category; bool specialCase = false; if ((leftCategory == ResolvedTypeCategory.STRING || leftCategory == ResolvedTypeCategory.LIST) && rightCategory == ResolvedTypeCategory.INTEGER && this.Op == Ops.MULTIPLICATION) { specialCase = true; } else if (leftCategory == ResolvedTypeCategory.STRING && this.Op == Ops.ADDITION) { if (rightCategory != ResolvedTypeCategory.NULL) { specialCase = true; } } if (!this.Target.CanAssignTo) { throw new ParserException(this.Target, "Cannot assign to this type of expression."); } if (!specialCase) { this.Value.ResolvedType.EnsureCanAssignToA(this.Value.FirstToken, this.Target.ResolvedType); } }
public static void Compile(ParserContext parser, ByteBuffer buffer, Variable variable, bool outputUsed) { if (!outputUsed) { throw new ParserException(variable, "This expression does nothing."); } int nameId = parser.GetId(variable.Name); Token token = variable.FirstToken; VariableId varId = variable.VarId; if (varId == null) { throw new ParserException(token, "Variable used but not declared."); } bool isClosureVar = varId.UsedByClosure; buffer.Add(token, isClosureVar ? OpCode.DEREF_CLOSURE : OpCode.LOCAL, isClosureVar ? varId.ClosureID : varId.ID, nameId); }
private IEnumerable <string> SetVariable(Node node, ParsingContext context) { if (node.Value[0] == '.') { return new[] { $"Can not use shorthand variable name ({node.Value})" } } ; //TODO better msg var variableId = new VariableId(node.Value); var variableExpressionNode = node.Children.First(); var errors = _parser.Parse(out var expression, variableExpressionNode.Value, context).FormatErrors(variableExpressionNode).ToList(); if (errors.Any()) { return(errors); } _statService.Get(variableId.StatId).AddOrUpdateVariable(variableId, expression !); return(Enumerable.Empty <string>()); }
// Shared code for functions/constructors/lambdas internal static void CompileFunctionArgs( ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, IList <Token> argNames, IList <Expression> argValues, List <int> offsetsForOptionalArgs, VariableId[] variableIds) { int bufferStartSize = buffer.Size; for (int i = 0; i < argNames.Count; ++i) { if (argValues[i] != null) { bcc.CompileExpression(parser, buffer, argValues[i], true); buffer.Add(argNames[i], OpCode.ASSIGN_LOCAL, i); offsetsForOptionalArgs.Add(buffer.Size - bufferStartSize); } } // Arguments that are actually closure variables and not plain locals need to be converted. for (int i = 0; i < argValues.Count; ++i) { VariableId varId = variableIds[i]; if (varId.UsedByClosure) { // It's simple to copy all passed args at function invocation time to locals, which, on // its own, is incorrect. Therefore add bytecode that will dereference those local ID's and // assign them to the proper closure ID. This eliminates the need to make a dinstinction in // CALL_FUNCTION between local and closure args. buffer.Add(null, OpCode.LOCAL, i); buffer.Add(null, OpCode.ASSIGN_CLOSURE, varId.ClosureID); } } }
public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, Assignment assignment) { Expression target = assignment.Target; Expression value = assignment.Value; ResolvedType targetAssignmentType = target.ResolvedType; if (targetAssignmentType == null) { throw new Exception(); // should be ANY if no type is set. } if (value.ResolvedType == ResolvedType.ANY && targetAssignmentType != ResolvedType.ANY) { value = new Cast(value.FirstToken, targetAssignmentType, value, value.Owner, false); } if (assignment.Op == Ops.EQUALS) { if (assignment.Target is Variable) { Variable varTarget = (Variable)assignment.Target; bcc.CompileExpression(parser, buffer, value, true); VariableId varId = varTarget.VarId; if (varId.UsedByClosure) { buffer.Add(assignment.OpToken, OpCode.ASSIGN_CLOSURE, varId.ClosureID); } else { buffer.Add(assignment.OpToken, OpCode.ASSIGN_LOCAL, varId.ID); } } else if (assignment.Target is BracketIndex) { BracketIndex bi = (BracketIndex)assignment.Target; bcc.CompileExpression(parser, buffer, bi.Root, true); bcc.CompileExpression(parser, buffer, bi.Index, true); bcc.CompileExpression(parser, buffer, value, true); buffer.Add(assignment.OpToken, OpCode.ASSIGN_INDEX, 0); } else if (assignment.Target is DotField) { DotField dotStep = (DotField)assignment.Target; if (dotStep.Root is ThisKeyword) { bcc.CompileExpression(parser, buffer, value, true); buffer.Add(assignment.OpToken, OpCode.ASSIGN_THIS_FIELD, parser.GetId(dotStep.FieldToken.Value)); } else { bcc.CompileExpression(parser, buffer, dotStep.Root, true); bcc.CompileExpression(parser, buffer, value, true); int nameId = parser.GetId(dotStep.FieldToken.Value); int localeScopedNameId = nameId * parser.GetLocaleCount() + parser.GetLocaleId(dotStep.Owner.FileScope.CompilationScope.Locale); buffer.Add( assignment.OpToken, OpCode.ASSIGN_FIELD, nameId, 0, localeScopedNameId, assignment.ClassOwner == null ? -1 : assignment.ClassOwner.ClassID, assignment.CompilationScope.ScopeNumId, -1, 0); } } else if (assignment.Target is FieldReference) { bcc.CompileExpression(parser, buffer, value, true); FieldReference fieldReference = (FieldReference)assignment.Target; if (fieldReference.Field.Modifiers.HasStatic) { buffer.Add( assignment.OpToken, OpCode.ASSIGN_STATIC_FIELD, ((ClassDefinition)fieldReference.Field.Owner).ClassID, fieldReference.Field.StaticMemberID); } else { buffer.Add( assignment.OpToken, OpCode.ASSIGN_THIS_FIELD, fieldReference.Field.MemberID); } } else { throw new Exception("This shouldn't happen."); } } else { Ops op = assignment.Op; if (assignment.Target is Variable) { Variable varTarget = (Variable)assignment.Target; VariableId varId = varTarget.VarId; bool isClosure = varId.UsedByClosure; int scopeId = isClosure ? varId.ClosureID : varId.ID; buffer.Add(varTarget.FirstToken, isClosure ? OpCode.DEREF_CLOSURE : OpCode.LOCAL, scopeId); bcc.CompileExpression(parser, buffer, value, true); buffer.Add(assignment.OpToken, OpCode.BINARY_OP, (int)op); buffer.Add(assignment.Target.FirstToken, isClosure ? OpCode.ASSIGN_CLOSURE : OpCode.ASSIGN_LOCAL, scopeId); } else if (assignment.Target is DotField) { DotField dotExpr = (DotField)assignment.Target; int fieldId = parser.GetId(dotExpr.FieldToken.Value); int localeScopedStepId = parser.GetLocaleCount() * fieldId + parser.GetLocaleId(dotExpr.Owner.FileScope.CompilationScope.Locale); bcc.CompileExpression(parser, buffer, dotExpr.Root, true); if (!(dotExpr.Root is ThisKeyword)) { buffer.Add(null, OpCode.DUPLICATE_STACK_TOP, 1); } buffer.Add( dotExpr.DotToken, OpCode.DEREF_DOT, fieldId, localeScopedStepId, assignment.ClassOwner == null ? -1 : assignment.ClassOwner.ClassID, assignment.CompilationScope.ScopeNumId, -1, 0); bcc.CompileExpression(parser, buffer, value, true); buffer.Add(assignment.OpToken, OpCode.BINARY_OP, (int)op); if (dotExpr.Root is ThisKeyword) { buffer.Add(assignment.OpToken, OpCode.ASSIGN_THIS_FIELD, fieldId); } else { int localeScopedNameId = fieldId * parser.GetLocaleCount() + parser.GetLocaleId(dotExpr.Owner.FileScope.CompilationScope.Locale); buffer.Add( assignment.OpToken, OpCode.ASSIGN_FIELD, fieldId, 0, localeScopedNameId, assignment.ClassOwner == null ? -1 : assignment.ClassOwner.ClassID, assignment.CompilationScope.ScopeNumId, -1, 0); } } else if (assignment.Target is BracketIndex) { BracketIndex indexExpr = (BracketIndex)assignment.Target; bcc.CompileExpression(parser, buffer, indexExpr.Root, true); bcc.CompileExpression(parser, buffer, indexExpr.Index, true); buffer.Add(null, OpCode.DUPLICATE_STACK_TOP, 2); buffer.Add(indexExpr.BracketToken, OpCode.INDEX); bcc.CompileExpression(parser, buffer, value, true); buffer.Add(assignment.OpToken, OpCode.BINARY_OP, (int)op); buffer.Add(assignment.OpToken, OpCode.ASSIGN_INDEX, 0); } else if (assignment.Target is FieldReference) { FieldReference fieldRef = (FieldReference)assignment.Target; FieldReferenceEncoder.Compile(parser, buffer, fieldRef, true); bcc.CompileExpression(parser, buffer, value, true); buffer.Add(assignment.OpToken, OpCode.BINARY_OP, (int)op); if (fieldRef.Field.Modifiers.HasStatic) { buffer.Add( assignment.OpToken, OpCode.ASSIGN_STATIC_FIELD, ((ClassDefinition)fieldRef.Field.Owner).ClassID, fieldRef.Field.StaticMemberID); } else { buffer.Add( assignment.OpToken, OpCode.ASSIGN_THIS_FIELD, fieldRef.Field.MemberID); } } else { throw new ParserException(assignment.OpToken, "Assignment is not allowed on this sort of expression."); } } }
private unsafe ushort getVariable(VariableId variableId) { byte bytes = getVariableBytes(variableId); ushort value = 0; byte[] array = new byte[bytes]; try { controlTransfer(0xC0, 0x81, 0, (ushort)variableId, array); } catch (Exception e) { throw new Exception("There was an error getting variable " + variableId.ToString() + " from the device.", e); } if (bytes == 1) { // read a single byte fixed (byte* pointer = array) { value = *(byte*)pointer; } } else { // read two bytes fixed (byte* pointer = array) { value = *(ushort*)pointer; } } return value; }
/// <summary> /// Returns the number of bytes that the variable takes. /// </summary> private byte getVariableBytes(VariableId variableId) { switch (variableId) { case VariableId.TARGET_VCC_ALLOWED_MINIMUM: case VariableId.TARGET_VCC_ALLOWED_MAXIMUM_RANGE: case VariableId.TARGET_VCC_MEASURED_MINIMUM: case VariableId.TARGET_VCC_MEASURED_MAXIMUM: case VariableId.PROGRAMMING_ERROR: case VariableId.LINE_A_IDENTITY: case VariableId.LINE_B_IDENTITY: case VariableId.SLOSCOPE_STATE: case VariableId.SW_MINOR: case VariableId.SW_MAJOR: case VariableId.HW_VER: case VariableId.SCK_DURATION: return 1; case VariableId.FVR_ADC: case VariableId.SLOSCOPE_OUTPUT_STATE: return 2; default: throw new Exception("Unrecognized variabledId " + variableId.ToString()); } }
public IteratorStr(String iteratorName, VariableId listData) { this.iteratorName = iteratorName; this.listData = listData; }
public double GetValue(VariableId id) => Stats[id.StatId].GetVariable(id);
public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, Increment increment, bool outputUsed) { if (!outputUsed) { throw new Exception("This should have been optimized into a += or -="); } if (increment.Root is Variable) { // OpCode re-use be damned. This should be not one, but two top-level op codes. // INCREMENT_INLINE and INCREMENT_POP (depending on whether outputUsed is true) // In fact, the code here in its current form is actually WRONG because someString++ will have // a '1' appended to it when it really should be an error if the variable is not an integer. // Same for the others below. Ideally the DUPLICATE_STACK_TOP op should be removed. Variable variable = (Variable)increment.Root; VariableId varId = variable.VarId; bool isClosureVar = varId.UsedByClosure; int scopeId = isClosureVar ? varId.ClosureID : varId.ID; bcc.CompileExpression(parser, buffer, increment.Root, true); if (increment.IsPrefix) { buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1); buffer.Add(variable.FirstToken, isClosureVar ? OpCode.ASSIGN_CLOSURE : OpCode.ASSIGN_LOCAL, scopeId); } else { buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1); buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION); buffer.Add(variable.FirstToken, isClosureVar ? OpCode.ASSIGN_CLOSURE : OpCode.ASSIGN_LOCAL, scopeId); } } else if (increment.Root is BracketIndex) { BracketIndex bracketIndex = (BracketIndex)increment.Root; bcc.CompileExpression(parser, buffer, bracketIndex.Root, true); bcc.CompileExpression(parser, buffer, bracketIndex.Index, true); buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 2); buffer.Add(bracketIndex.BracketToken, OpCode.INDEX); if (increment.IsPrefix) { buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.ASSIGN_INDEX, 1); } else { buffer.Add(increment.IncrementToken, OpCode.STACK_INSERTION_FOR_INCREMENT); buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.ASSIGN_INDEX, 0); } } else if (increment.Root is DotField) { DotField dotStep = (DotField)increment.Root; bcc.CompileExpression(parser, buffer, dotStep.Root, true); buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1); int nameId = parser.GetId(dotStep.FieldToken.Value); int localeScopedNameId = nameId * parser.GetLocaleCount() + parser.GetLocaleId(dotStep.Owner.FileScope.CompilationScope.Locale); int originClassId = increment.ClassOwner == null ? -1 : increment.ClassOwner.ClassID; int originAssemblyId = increment.CompilationScope.ScopeNumId; buffer.Add( dotStep.DotToken, OpCode.DEREF_DOT, nameId, localeScopedNameId, originClassId, increment.CompilationScope.ScopeNumId, -1, 0); if (increment.IsPrefix) { buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.ASSIGN_FIELD, nameId, 1, localeScopedNameId, originClassId, originAssemblyId, -1, 0); } else { buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 2); buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.ASSIGN_FIELD, nameId, 0, localeScopedNameId, originClassId, originAssemblyId, -1, 0); buffer.Add(increment.IncrementToken, OpCode.STACK_SWAP_POP); } } else if (increment.Root is FieldReference) { FieldReference fr = (FieldReference)increment.Root; bool isStatic = fr.Field.Modifiers.HasStatic; ClassDefinition cd = (ClassDefinition)fr.Field.Owner; int memberId = isStatic ? fr.Field.StaticMemberID : fr.Field.MemberID; bcc.CompileExpression(parser, buffer, fr, true); if (increment.IsPrefix) { buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1); } else { buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1); buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION); } Token token = increment.IsPrefix ? increment.FirstToken : fr.FirstToken; if (isStatic) { buffer.Add(token, OpCode.ASSIGN_STATIC_FIELD, ((ClassDefinition)fr.Field.Owner).ClassID, memberId); } else { buffer.Add(token, OpCode.ASSIGN_THIS_FIELD, memberId); } } else { throw new ParserException(increment.IncrementToken, "Cannot apply " + (increment.IsIncrement ? "++" : "--") + " to this sort of expression."); } }