public override void EmitCode(IBlockContext context, bool dropResult) { TO2Type leftType = left.ResultType(context); TO2Type rightType = right.ResultType(context); if (context.HasErrors) { return; } IOperatorEmitter leftEmitter = leftType.AllowedSuffixOperators(context.ModuleContext) .GetMatching(context.ModuleContext, op, rightType); IOperatorEmitter rightEmitter = rightType.AllowedPrefixOperators(context.ModuleContext) .GetMatching(context.ModuleContext, op, leftType); if (leftEmitter == null && rightEmitter == null) { context.AddError(new StructuralError( StructuralError.ErrorType.IncompatibleTypes, $"Cannot {op} a {leftType} with a {rightType}", Start, End )); return; } right.Prepare(context); left.EmitCode(context, false); rightEmitter?.OtherType.AssignFrom(context.ModuleContext, leftType).EmitConvert(context); right.EmitCode(context, false); leftEmitter?.OtherType.AssignFrom(context.ModuleContext, rightType).EmitConvert(context); if (context.HasErrors) { return; } if (leftEmitter != null) { leftEmitter.EmitCode(context, this); } else { rightEmitter.EmitCode(context, this); } if (dropResult) { context.IL.Emit(OpCodes.Pop); } }
public override TO2Type ResultType(IBlockContext context) { TO2Type leftType = left.ResultType(context); TO2Type rightType = right.ResultType(context); IOperatorEmitter operatorEmitter = leftType.AllowedSuffixOperators(context.ModuleContext) .GetMatching(context.ModuleContext, op, rightType) ?? rightType.AllowedPrefixOperators(context.ModuleContext) .GetMatching(context.ModuleContext, op, leftType); if (operatorEmitter == null) { context.AddError(new StructuralError( StructuralError.ErrorType.IncompatibleTypes, $"Cannot {op} a {leftType} with a {rightType}", Start, End )); return(BuiltinType.Unit); } return(operatorEmitter.ResultType); }
public override IOperatorCollection AllowedPrefixOperators(ModuleContext context) => aliasedType.AllowedPrefixOperators(declaredModule);