public override StatementSyntax GetAssignmentStatement(AssignmentTarget target, SourceProperty p, IdentifierNameSyntax sourceObjectVariableName) { return(target switch { AssignmentTarget.SourceClass => GetSourceMethodCallAssignmentStatement(p, sourceObjectVariableName, "ToImmutable"), AssignmentTarget.SourceToSource => p.GetAssignmentStatement(p.GetAccessExpression(sourceObjectVariableName)), _ => GetTargetMethodCallAssignmentStatement(p, sourceObjectVariableName, "AddRange") });
internal static string AnalysisDictionaryKey(VariableExpressionAst varExprAst) { if (varExprAst == null) { return(String.Empty); } return(String.Format(CultureInfo.CurrentCulture, "{0}s{1}e{2}", AssignmentTarget.GetUnaliasedVariableName(varExprAst.VariablePath), varExprAst.Extent.StartOffset, varExprAst.Extent.EndOffset )); }
private void AnalyzeBlock(BitArray assignedBitArray, Block block) { foreach (Ast ast in block._asts) { VariableExpressionAst ast2 = ast as VariableExpressionAst; if (ast2 != null) { VariablePath variablePath = ast2.VariablePath; if (variablePath.IsAnyLocal()) { string unaliasedVariableName = GetUnaliasedVariableName(variablePath); VariableAnalysisDetails details = this._variables[unaliasedVariableName]; if (details.Automatic) { ast2.TupleIndex = details.LocalTupleIndex; ast2.Automatic = true; } else { ast2.TupleIndex = (assignedBitArray[details.BitIndex] && !details.PreferenceVariable) ? details.LocalTupleIndex : -2; } } } else { AssignmentTarget target = ast as AssignmentTarget; if (target != null) { if (target._targetAst != null) { this.CheckLHSAssign(target._targetAst, assignedBitArray); } else { this.CheckLHSAssignVar(target._variableName, assignedBitArray, target._type); } } else { DataStatementAst item = ast as DataStatementAst; if (item != null) { VariableAnalysisDetails details2 = this.CheckLHSAssignVar(item.Variable, assignedBitArray, typeof(object)); item.TupleIndex = details2.LocalTupleIndex; details2.AssociatedAsts.Add(item); } } } } }
/// <summary> /// Visit variable expression ast /// </summary> /// <param name="variableExpressionAst"></param> /// <returns></returns> public override object VisitVariableExpression(VariableExpressionAst variableExpressionAst) { if (variableExpressionAst == null) { return(null); } var varPath = variableExpressionAst.VariablePath; if (_variables.ContainsKey(AssignmentTarget.GetUnaliasedVariableName(varPath))) { var details = _variables[AssignmentTarget.GetUnaliasedVariableName(varPath)]; Current.AddAst(new VariableTarget(variableExpressionAst)); details.AssociatedAsts.Add(variableExpressionAst); } return(base.VisitVariableExpression(variableExpressionAst)); }
/// <summary> /// Visit assignment statement /// </summary> /// <param name="assignmentStatementAst"></param> /// <returns></returns> public override object VisitAssignmentStatement(AssignmentStatementAst assignmentStatementAst) { if (assignmentStatementAst == null) { return(null); } base.VisitAssignmentStatement(assignmentStatementAst); foreach (var assignTarget in GetAssignmentTargets(assignmentStatementAst.Left)) { var leftAst = assignTarget; while (leftAst is AttributedExpressionAst) { leftAst = ((AttributedExpressionAst)leftAst).Child; } if (leftAst is VariableExpressionAst) { var varPath = ((VariableExpressionAst)leftAst).VariablePath; if (_variables.ContainsKey(AssignmentTarget.GetUnaliasedVariableName(varPath))) { var details = _variables[AssignmentTarget.GetUnaliasedVariableName(varPath)]; details.AssignedBlocks.Add(Current); } Current.AddAst(new AssignmentTarget(assignmentStatementAst)); } else { // We skip things like $a.test = 3. In this case we will just test // for variable $a assignTarget.Visit(this.Decorator); } } return(null); }
protected DataElement CreateTargetElement(AssignmentTarget target) { switch (target) { case AssignmentTarget.Variable variable: return(_dataSet.CreateVariable(variable.VariableType, variable.VariableId)); case AssignmentTarget.VariablePointer pointer: return(_dataSet.CreateVariablePointer(pointer.VariableType, pointer.PointerId)); case AssignmentTarget.SpecialString sstr: return(_dataSet.CreateVariable(sstr.Id, 0)); case AssignmentTarget.Local local: throw new FormatException($"Unexpected local variable in assignment: {local.Id}"); case AssignmentTarget.IntPointer pointer: return(_dataSet.CreateIntPointer(pointer.PointerId)); default: throw new FormatException($"Invalid assignment target: {target.GetType().Name}"); } }
/// <summary> /// pre-run for emitting the needed entities before emitting the real code /// - emits sequence variable declarations (only once for every variable, declaration only possible at assignment targets) /// </summary> private void EmitNeededVarEntities(AssignmentTarget tgt, SourceBuilder source) { source.AppendFront(COMP_HELPER.DeclareResultVar(tgt)); switch (tgt.AssignmentTargetType) { case AssignmentTargetType.Var: { AssignmentTargetVar var = (AssignmentTargetVar)tgt; EmitVarIfNew(var.DestVar, source); break; } case AssignmentTargetType.YieldingToVar: { AssignmentTargetYieldingVar var = (AssignmentTargetYieldingVar)tgt; EmitVarIfNew(var.DestVar, source); break; } default: break; } }
private void ProcessParameters(IEnumerable <ParameterAst> parameters) { foreach (var parameter in parameters) { var variablePath = parameter.Name.VariablePath; bool isSwitchOrMandatory = false; Type type = null; foreach (var paramAst in parameter.Attributes) { if (paramAst is TypeConstraintAst) { if (type == null) { type = paramAst.TypeName.GetReflectionType(); } if (String.Equals(paramAst.TypeName.FullName, "switch", StringComparison.OrdinalIgnoreCase)) { isSwitchOrMandatory = true; } } else if (paramAst is AttributeAst) { var args = (paramAst as AttributeAst).NamedArguments; if (args != null) { foreach (NamedAttributeArgumentAst arg in args) { if (String.Equals(arg.ArgumentName, "mandatory", StringComparison.OrdinalIgnoreCase) && String.Equals(arg.Argument.Extent.Text, "$true", StringComparison.OrdinalIgnoreCase)) { isSwitchOrMandatory = true; } } } } } var varName = AssignmentTarget.GetUnaliasedVariableName(variablePath); var details = _variables[varName]; details.Type = type ?? details.Type ?? typeof(object); if (parameter.DefaultValue != null) { var assignTarget = new AssignmentTarget(varName, type); if (parameter.DefaultValue is ConstantExpressionAst) { assignTarget.Constant = (parameter.DefaultValue as ConstantExpressionAst).Value; assignTarget.Type = assignTarget.Constant == null ? typeof(object) : assignTarget.Constant.GetType(); } Entry.AddAst(assignTarget); } else if (isSwitchOrMandatory) { // Consider switch or mandatory parameter as already initialized Entry.AddAst(new AssignmentTarget(varName, type)); } else { VariableTarget varTarget = new VariableTarget(parameter.Name); varTarget.Type = details.Type; Entry.AddAst(varTarget); } } }
public ParameterGenerator AddPropertyAssignmentBlock(AssignmentTarget target) { _constructor.Statements.AddRange(GeneratePropertyAssignmentBlock(target)); return(this); }
protected abstract IEnumerable <StatementSyntax> GeneratePropertyAssignmentBlock(AssignmentTarget target);
protected override IEnumerable <StatementSyntax> GeneratePropertyAssignmentBlock(AssignmentTarget target) => SourceType.GenerateConditionalPropertyAssginmentBlock(target, Name);
/// <summary> /// Used to analyze scriptbloct, functionmemberast or functiondefinitionast /// </summary> /// <param name="ast"></param> /// <returns></returns> public void AnalyzeImpl(Ast ast, VariableAnalysis outerAnalysis) { if (!(ast is ScriptBlockAst || ast is FunctionMemberAst || ast is FunctionDefinitionAst)) { return; } _variables = FindAllVariablesVisitor.Visit(ast); Init(); if (ast is FunctionMemberAst || ast is FunctionDefinitionAst) { IEnumerable <ParameterAst> parameters = FindParameters(ast, ast.GetType()); if (parameters != null) { ProcessParameters(parameters); } } else { ScriptBlockAst sbAst = ast as ScriptBlockAst; if (sbAst != null && sbAst.ParamBlock != null && sbAst.ParamBlock.Parameters != null) { ProcessParameters(sbAst.ParamBlock.Parameters); } } if (ast is FunctionMemberAst) { (ast as FunctionMemberAst).Body.Visit(this.Decorator); } else if (ast is FunctionDefinitionAst) { (ast as FunctionDefinitionAst).Body.Visit(this.Decorator); } else { ast.Visit(this.Decorator); } Ast parent = ast; while (parent.Parent != null) { parent = parent.Parent; } List <TypeDefinitionAst> classes = parent.FindAll(item => item is TypeDefinitionAst && (item as TypeDefinitionAst).IsClass, true) .Cast <TypeDefinitionAst>().ToList(); if (outerAnalysis != null) { // Initialize the variables from outside var outerDictionary = outerAnalysis.InternalVariablesDictionary; foreach (var details in outerDictionary.Values) { if (details.DefinedBlock != null) { var assignTarget = new AssignmentTarget(details.RealName, details.Type); assignTarget.Constant = details.Constant; if (!_variables.ContainsKey(assignTarget.Name)) { _variables.Add(assignTarget.Name, new VariableAnalysisDetails { Name = assignTarget.Name, RealName = assignTarget.Name, Type = assignTarget.Type }); } Entry.AddFirstAst(assignTarget); } } foreach (var key in _variables.Keys) { if (outerDictionary.ContainsKey(key)) { var outerItem = outerDictionary[key]; var innerItem = _variables[key]; innerItem.Constant = outerItem.Constant; innerItem.Name = outerItem.Name; innerItem.RealName = outerItem.RealName; innerItem.Type = outerItem.Type; } } } var dictionaries = Block.SparseSimpleConstants(_variables, Entry, classes); VariablesDictionary = dictionaries.Item1; InternalVariablesDictionary = new Dictionary <string, VariableAnalysisDetails>(StringComparer.OrdinalIgnoreCase); foreach (var KVP in dictionaries.Item2) { var analysis = KVP.Value; if (analysis == null) { continue; } if (!InternalVariablesDictionary.ContainsKey(analysis.RealName)) { InternalVariablesDictionary.Add(analysis.RealName, analysis); } else { InternalVariablesDictionary[analysis.RealName] = analysis; } } }
public IEnumerable <StatementSyntax> GenerateConditionalPropertyAssginmentBlock(AssignmentTarget target, IdentifierNameSyntax sourceObjectVariableName) => new StatementSyntax[] { IfStatement( condition: BinaryExpression( SyntaxKind.NotEqualsExpression, left: sourceObjectVariableName, right: LiteralExpression(SyntaxKind.NullLiteralExpression)), statement: Block(GeneratePropertyAssginmentBlock(target, sourceObjectVariableName))) };
protected void SetAssignmentTarget(TargetInstruction instruction) { if (_currentAssignmentTarget != null) { throw new FormatException("Assignment target already set"); } switch (instruction.Target) { // special strings case DataElement.SStr sstr: _currentAssignmentTarget = new AssignmentTarget.SpecialString(sstr.FlagType.StringValue); break; // integer variable pointers case DataElement.VInt vint when vint.FlagId.IsPointer: _currentAssignmentTarget = new AssignmentTarget.VariablePointer(vint.FlagType.StringValue, vint.FlagId.PointerId); break; // integer variables case DataElement.VInt vint: // range checks if (vint.FlagId.IntValue < 0) { throw new ArgumentOutOfRangeException(nameof(vint.FlagId.IntValue), vint.FlagId.IntValue, "Flag index must be positive"); } if (vint.FlagId.IntValue >= GlobalFlagTableSize && vint.FlagType.StringValue == YksFormat.GlobalFlag) { throw new ArgumentOutOfRangeException(nameof(vint.FlagId.IntValue), vint.FlagId.IntValue, "Global flag index must be smaller than " + GlobalFlagTableSize); } if (vint.FlagId.IntValue >= LocalFlagTableSize && vint.FlagType.StringValue == YksFormat.Flag) { throw new ArgumentOutOfRangeException(nameof(vint.FlagId.IntValue), vint.FlagId.IntValue, "Local flag index must be smaller than " + LocalFlagTableSize); } _currentAssignmentTarget = new AssignmentTarget.Variable(vint.FlagType.StringValue, vint.FlagId.IntValue); break; // string variable pointers case DataElement.VStr vstr when vstr.FlagId.IsPointer: _currentAssignmentTarget = new AssignmentTarget.VariablePointer(vstr.FlagType.StringValue, vstr.FlagId.PointerId); break; // integer variables case DataElement.VStr vstr: // range checks if (vstr.FlagId.IntValue < 0) { throw new ArgumentOutOfRangeException(nameof(vstr.FlagId.IntValue), vstr.FlagId.IntValue, "String index must be positive"); } if (vstr.FlagId.IntValue >= GlobalStringTableSize && vstr.FlagType.StringValue == YksFormat.GlobalString) { throw new ArgumentOutOfRangeException(nameof(vstr.FlagId.IntValue), vstr.FlagId.IntValue, "String flag index must be smaller than " + GlobalStringTableSize); } if (vstr.FlagId.IntValue >= LocalStringTableSize && vstr.FlagType.StringValue == YksFormat.String) { throw new ArgumentOutOfRangeException(nameof(vstr.FlagId.IntValue), vstr.FlagId.IntValue, "String flag index must be smaller than " + LocalStringTableSize); } _currentAssignmentTarget = new AssignmentTarget.Variable(vstr.FlagType.StringValue, vstr.FlagId.IntValue); break; // local variables case DataElement.VLoc vloc: if (vloc.Id >= Script.InstructionList.MaxLocals) { throw new ArgumentOutOfRangeException(nameof(vloc.Id), vloc.Id, "Local variable id must be smaller than local variable pool size (" + Script.InstructionList.MaxLocals + ")"); } _currentAssignmentTarget = new AssignmentTarget.Local(vloc.Id); break; // int pointers case DataElement.CInt cint: cint.Value.PointerId = _flagPointerId++; _currentAssignmentTarget = new AssignmentTarget.IntPointer(cint.Value.PointerId); break; default: throw new ArgumentOutOfRangeException(nameof(instruction), "Invalid assignment target: " + instruction); } }
protected Statement ReadStatement() { var instruction = ReadInstruction(); switch (instruction) { case LabelInstruction label: Debug.Assert(label.Name != "else" && label.Name != "}"); if (label.Name == "{") { return(ReadBlockStatement()); } return(new JumpLabelStmt { Name = label.Name.EscapeIdentifier() }); case CallInstruction func: #region Handle assignments if (func.Name == "=") { if (_currentAssignmentTarget == null) { throw new FormatException("No assignment target set"); } Expression expr; if (func.Arguments.Length == 0) { // a call to =() with no arguments means the result of the following function call is assigned if (CurrentInstruction is CallInstruction callInstruction) { expr = new FunctionCallExpr { CallStmt = new FunctionCallStmt { MethodName = callInstruction.Name, Arguments = MapToExpressions(callInstruction.Arguments) } }; _currentInstructionOffset++; } else { throw new FormatException("A parameterless call to =() must be followed by a function call, found " + CurrentInstruction); } } else { // otherwise, the arguments are alternating operands and operators expr = ToExpression(func.Arguments); } if (_currentAssignmentTarget is AssignmentTarget.Local local) { _locals[local.Id] = expr; _currentAssignmentTarget = null; return(null); } var assigment = new AssignmentStmt { Target = _currentAssignmentTarget, Expression = expr }; _currentAssignmentTarget = null; return(assigment); } #endregion var callStatement = new FunctionCallStmt { MethodName = func.Name, Arguments = MapToExpressions(func.Arguments) }; #region Handle body functions if (CurrentInstruction is LabelInstruction startLabel && startLabel.Name == "{") { _currentInstructionOffset++; // skip opening brace var body = ReadBlockStatement(); #region Handle if statements if (callStatement.MethodName.ToLower() == "if") { if (Script.InstructionList.Count <= _currentInstructionOffset || !(Script.InstructionList[_currentInstructionOffset] is LabelInstruction elseKeyword) || elseKeyword.Name != "else") { // no else block return new IfStmt { Function = callStatement, Body = body } } ; BlockStmt elseBody; // skip else keyword _currentInstructionOffset++; if (Script.InstructionList[_currentInstructionOffset] is LabelInstruction elseStart && elseStart.Name == "{") { // skip opening brace _currentInstructionOffset++; elseBody = ReadBlockStatement(); } else { // "Kimi o Aogi Otome wa Hime ni" has these bodyless else keywords in data01:system/selectjumpstart.yks Console.WriteLine("Warning: Loose else keyword without body"); elseBody = new BlockStmt(); //throw new FormatException("Else keyword must be followed by an opening brace"); } return(new IfStmt { Function = callStatement, Body = body, ElseBody = elseBody }); } #endregion return(new BodyFunctionStmt { Function = callStatement, Body = body }); } #endregion return(callStatement); case TargetInstruction target: SetAssignmentTarget(target); return(null); default: throw new FormatException("Invalid statement instruction: " + instruction); } }
protected TargetInstruction CreateTargetInstruction(AssignmentTarget target) { return(new TargetInstruction(CreateTargetElement(target), _instructions)); }
public abstract StatementSyntax GetAssignmentStatement( AssignmentTarget target, SourceProperty p, IdentifierNameSyntax sourceObjectVariableName);
private IEnumerable <StatementSyntax> GeneratePropertyAssginmentBlock(AssignmentTarget target, IdentifierNameSyntax sourceObjectVariableName) => Properties.Select(p => PropertyRule.GetRule(p).GetAssignmentStatement(target, p, sourceObjectVariableName));
public IEnumerable <StatementSyntax> GeneratePropertyAssginmentBlockWithNullCheck(AssignmentTarget target, IdentifierNameSyntax sourceObjectVariableName) => new[] { GenerateNullCheck(sourceObjectVariableName) }.Concat(GeneratePropertyAssginmentBlock(target, sourceObjectVariableName));