From b5c3a537c2fd033691c0e277dad7cfac9118cd71 Mon Sep 17 00:00:00 2001 From: InformaTiger Date: Fri, 1 Jul 2022 15:43:27 +0200 Subject: [PATCH 01/12] Fixed error: 1d and 1f are ints --- src/client/compiler/lexer/Lexer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/compiler/lexer/Lexer.ts b/src/client/compiler/lexer/Lexer.ts index 8de682a5..f5999139 100644 --- a/src/client/compiler/lexer/Lexer.ts +++ b/src/client/compiler/lexer/Lexer.ts @@ -914,7 +914,7 @@ export class Lexer { } if (this.currentChar == 'd' || this.currentChar == 'f') { - tt == TokenType.floatingPointConstant; + tt = TokenType.floatingPointConstant; this.next(); if (radix != 10) { this.pushError("Eine float/double-Konstante darf nicht mit 0, 0b oder 0x beginnen.", this.pos - posStart, "error", this.line, this.column - (this.pos - posStart)); From 5c2f3400207b5369023fb2dad3e3ad3001b8b388 Mon Sep 17 00:00:00 2001 From: InformaTiger Date: Fri, 1 Jul 2022 17:37:34 +0200 Subject: [PATCH 02/12] automaticToString --- src/client/compiler/parser/CodeGenerator.ts | 107 +++++++++++++------- src/client/compiler/types/Class.ts | 4 +- src/client/compiler/types/PrimitiveTypes.ts | 51 +++------- src/client/compiler/types/Types.ts | 8 +- src/client/interpreter/Interpreter.ts | 7 +- src/client/tools/StringTools.ts | 8 ++ 6 files changed, 105 insertions(+), 80 deletions(-) diff --git a/src/client/compiler/parser/CodeGenerator.ts b/src/client/compiler/parser/CodeGenerator.ts index 7247aad2..b62e0b65 100644 --- a/src/client/compiler/parser/CodeGenerator.ts +++ b/src/client/compiler/parser/CodeGenerator.ts @@ -1,16 +1,15 @@ import { Error, QuickFix, ErrorLevel } from "../lexer/Lexer.js"; import { TextPosition, TokenType, TokenTypeReadable } from "../lexer/Token.js"; import { ArrayType } from "../types/Array.js"; -import { Klass, Interface, StaticClass, Visibility, getVisibilityUpTo } from "../types/Class.js"; +import { Klass, Interface, StaticClass, Visibility, getVisibilityUpTo, UnboxableKlass } from "../types/Class.js"; import { booleanPrimitiveType, charPrimitiveType, floatPrimitiveType, intPrimitiveType, stringPrimitiveType, objectType, nullType, voidPrimitiveType, varType, doublePrimitiveType } from "../types/PrimitiveTypes.js"; import { Attribute, Type, Variable, Value, PrimitiveType, UsagePositions, Method, Heap, getTypeIdentifier, Parameterlist } from "../types/Types.js"; import { ASTNode, AttributeDeclarationNode, BinaryOpNode, ClassDeclarationNode, ConstantNode, DoWhileNode, ForNode, IdentifierNode, IfNode, IncrementDecrementNode, MethodcallNode, MethodDeclarationNode, NewObjectNode, ReturnNode, SelectArrayElementNode, SelectArributeNode, SuperconstructorCallNode, SuperNode, ThisNode, UnaryOpNode, WhileNode, LocalVariableDeclarationNode, ArrayInitializationNode, NewArrayNode, PrintNode, CastManuallyNode, EnumDeclarationNode, TermNode, SwitchNode, ScopeNode, ParameterNode, ForNodeOverCollecion, ConstructorCallNode } from "./AST.js"; import { LabelManager } from "./LabelManager.js"; -import { Module, ModuleStore, MethodCallPosition } from "./Module.js"; -import { AssignmentStatement, InitStackframeStatement, JumpAlwaysStatement, Program, Statement, BeginArrayStatement, NewObjectStatement, JumpOnSwitchStatement, Breakpoint, ExtendedForLoopCheckCounterAndGetElement } from "./Program.js"; +import { Module, ModuleStore } from "./Module.js"; +import { AssignmentStatement, InitStackframeStatement, JumpAlwaysStatement, Program, Statement, BeginArrayStatement, NewObjectStatement, JumpOnSwitchStatement, ExtendedForLoopCheckCounterAndGetElement } from "./Program.js"; import { SymbolTable } from "./SymbolTable.js"; import { Enum, EnumInfo } from "../types/Enum.js"; -import { InputClass } from "../../runtimelibrary/Input.js"; type StackType = { type: Type, @@ -860,38 +859,64 @@ export class CodeGenerator { if (!castInfo.automatic) { return false; } - if (castInfo.needsStatement) { - this.pushStatements({ - type: TokenType.castValue, - newType: typeTo, - position: position - }); - } + this.pushStatements({ + type: TokenType.castValue, + newType: typeTo, + position: position + }); } return true; } - getToStringStatement(type: Klass, position: TextPosition): Statement { - let toStringMethod = type.getMethodBySignature("toString()"); - if (toStringMethod != null && toStringMethod.getReturnType() == stringPrimitiveType) { + ensureAutomaticToString(typeFrom: Type, codepos: number = undefined, textposition?: TextPosition): boolean { + if (typeFrom == stringPrimitiveType) return true; + if (typeFrom == voidPrimitiveType) return false; + let automaticToString: Method; + + if (typeFrom instanceof PrimitiveType) { + automaticToString = new Method("toString", new Parameterlist([]), stringPrimitiveType, (parameters: Value[]) => { + let value = parameters[0]; + return ((value.type).valueToString(value)); + }, false, true); - return { + } + if ((typeFrom instanceof Klass) || (typeFrom == nullType)) { + + let toStringMethod: Method; + if (typeFrom == nullType) { + toStringMethod = objectType.getMethodBySignature("toString()"); + } + else { + toStringMethod = (typeFrom).getMethodBySignature("toString()"); + } + if (toStringMethod != null && toStringMethod.getReturnType() == stringPrimitiveType) { + automaticToString = new Method(toStringMethod.identifier, toStringMethod.parameterlist, stringPrimitiveType, (parameters: Value[]) => { + let value = parameters[0].value; + if (value == null) return "null"; + return toStringMethod.invoke(parameters); + }, toStringMethod.isAbstract, true, toStringMethod.documentation, toStringMethod.isConstructor); + + } + + } + if (automaticToString != undefined) { + this.insertOrPushStatements({ type: TokenType.callMethod, - position: position, - method: toStringMethod, + position: textposition, + method: automaticToString, isSuperCall: false, stackframeBegin: -1, stepFinished: false - }; - - - } else { - return null; + }, codepos); + return true; } + return false; + } + checkIfAssignmentInstedOfEqual(nodeFrom: ASTNode, conditionType?: Type) { if (nodeFrom == null) return; @@ -1034,6 +1059,11 @@ export class CodeGenerator { } } + insertOrPushStatements(statements: Statement | Statement[], pos?: number) { + if (pos == null && pos == undefined) this.pushStatements(statements); + else this.insertStatements(pos, statements); + } + removeLastStatement() { let lst = this.currentProgram.statements.pop(); if (this.currentProgram.labelManager != null) { @@ -1375,7 +1405,7 @@ export class CodeGenerator { let type = this.processNode(node.text); if (type != null) { - if (!this.ensureAutomaticCasting(type.type, stringPrimitiveType)) { + if (!this.ensureAutomaticToString(type.type)) { this.pushError("Die Methoden print und println erwarten einen Parameter vom Typ String. Gefunden wurde ein Wert vom Typ " + type.type?.identifier + ".", node.position); } } @@ -3158,6 +3188,8 @@ export class CodeGenerator { if (leftType == null || leftType.type == null || rightType == null || rightType.type == null) return null; + let convertedLeftType = leftType.type; + if (isAssignment) { if (!this.ensureAutomaticCasting(rightType.type, leftType.type, node.position, node.firstOperand)) { this.pushError("Der Wert vom Datentyp " + rightType.type.identifier + " auf der rechten Seite kann der Variablen auf der linken Seite (Datentyp " + leftType.type.identifier + ") nicht zugewiesen werden.", node.position); @@ -3196,6 +3228,20 @@ export class CodeGenerator { let unboxableLeft = leftType.type["unboxableAs"]; let unboxableRight = rightType.type["unboxableAs"]; + + if (resultType == null && node.operator == TokenType.plus) { + if (rightType.type == stringPrimitiveType) { + if (this.ensureAutomaticToString(leftType.type, programPosAfterLeftOpoerand, node.firstOperand.position)) { + resultType = stringPrimitiveType; + convertedLeftType = stringPrimitiveType; + } + } else if (leftType.type == stringPrimitiveType) { + if (this.ensureAutomaticToString(rightType.type, undefined, node.firstOperand.position)) { + resultType = stringPrimitiveType; + } + } + } + if (resultType == null && (unboxableLeft != null || unboxableRight != null)) { let leftTypes: Type[] = unboxableLeft == null ? [leftType.type] : unboxableLeft; let rightTypes: Type[] = unboxableRight == null ? [rightType.type] : unboxableRight; @@ -3206,6 +3252,7 @@ export class CodeGenerator { if (resultType != null) { leftType.type = lt; rightType.type = rt; + convertedLeftType = lt; break; } } @@ -3213,18 +3260,6 @@ export class CodeGenerator { } } - // Situation Object + String: insert toString()-Method - if (resultType == null && node.operator == TokenType.plus) { - if (leftType.type instanceof Klass && rightType.type == stringPrimitiveType) { - this.insertStatements(programPosAfterLeftOpoerand, this.getToStringStatement(leftType.type, node.firstOperand.position)); - resultType = stringPrimitiveType; - leftType.type = stringPrimitiveType; - } else if (rightType.type instanceof Klass && leftType.type == stringPrimitiveType) { - this.pushStatements(this.getToStringStatement(rightType.type, node.firstOperand.position)); - resultType = stringPrimitiveType; - } - } - if (node.operator in [TokenType.and, TokenType.or]) { this.checkIfAssignmentInstedOfEqual(node.firstOperand); @@ -3262,7 +3297,7 @@ export class CodeGenerator { this.pushStatements({ type: TokenType.binaryOp, - leftType: leftType.type, + leftType: convertedLeftType, operator: node.operator, position: node.position }); diff --git a/src/client/compiler/types/Class.ts b/src/client/compiler/types/Class.ts index 70003878..fb4a8229 100644 --- a/src/client/compiler/types/Class.ts +++ b/src/client/compiler/types/Class.ts @@ -622,9 +622,7 @@ export class Klass extends Type { public canCastTo(type: Type): boolean { - if (type == stringPrimitiveType) { - return true; - } + // casting something to a String by calling toString() is neither possible in Java nor makes sense in my opinion if (type instanceof Klass) { let baseClass: Klass = this; diff --git a/src/client/compiler/types/PrimitiveTypes.ts b/src/client/compiler/types/PrimitiveTypes.ts index 202a7ef5..236e50da 100644 --- a/src/client/compiler/types/PrimitiveTypes.ts +++ b/src/client/compiler/types/PrimitiveTypes.ts @@ -1,4 +1,4 @@ -import { TokenType } from "../lexer/Token.js"; +import { TokenType, TokenTypeReadable } from "../lexer/Token.js"; import { ArrayType } from "./Array.js"; import { Interface, Klass, setBooleanPrimitiveTypeCopy } from "./Class.js"; import { ObjectClass } from "./ObjectClass.js"; @@ -9,6 +9,7 @@ import { FloatClass } from "./boxedTypes/FloatClass.js"; import { CharacterClass } from "./boxedTypes/CharacterClass.js"; import { BooleanClass } from "./boxedTypes/BooleanClass.js"; import { DoubleClass } from "./boxedTypes/DoubleClass.js"; +import { floatToString, nullToString } from "../../tools/StringTools.js"; export class NullType extends Type { @@ -107,7 +108,6 @@ export class IntPrimitiveType extends PrimitiveType { this.canCastToMap = { "float": { automatic: true, needsStatement: false }, "double": { automatic: true, needsStatement: false }, - "String": { automatic: true, needsStatement: true }, "char": { automatic: true, needsStatement: true }, "int": { automatic: true, needsStatement: false }, "long": { automatic: true, needsStatement: false }, @@ -129,14 +129,6 @@ export class IntPrimitiveType extends PrimitiveType { value: value.value }; } - - if (type == stringPrimitiveType) { - return { - type: type, - value: "" + value.value - } - } - if (type == charPrimitiveType) { return { type: type, @@ -279,7 +271,6 @@ export class LongPrimitiveType extends IntPrimitiveType { this.canCastToMap = { "float": { automatic: true, needsStatement: false }, "double": { automatic: true, needsStatement: false }, - "String": { automatic: true, needsStatement: true }, "char": { automatic: true, needsStatement: true }, "int": { automatic: false, needsStatement: false }, "long": { automatic: true, needsStatement: false }, @@ -328,9 +319,8 @@ export class FloatPrimitiveType extends PrimitiveType { "int": { automatic: false, needsStatement: true }, "double": { automatic: true, needsStatement: false }, "float": { automatic: true, needsStatement: false }, - "String": { automatic: true, needsStatement: true }, - "Float": { automatic: true, needsStatement: false }, - "Double": { automatic: true, needsStatement: false }, + "Float": { automatic: true, needsStatement: true }, + "Double": { automatic: true, needsStatement: true }, } } @@ -341,13 +331,6 @@ export class FloatPrimitiveType extends PrimitiveType { public castTo(value: Value, type: Type): Value { - if (type == stringPrimitiveType) { - return { - type: type, - value: "" + value.value - } - } - if (type == intPrimitiveType) { return { type: type, @@ -362,6 +345,8 @@ export class FloatPrimitiveType extends PrimitiveType { } } + public valueToString(value: Value): string { + return floatToString(value.value); } @@ -457,9 +442,8 @@ export class DoublePrimitiveType extends PrimitiveType { "int": { automatic: false, needsStatement: true }, "float": { automatic: true, needsStatement: false }, "double": { automatic: true, needsStatement: false }, - "String": { automatic: true, needsStatement: true }, - "Float": { automatic: true, needsStatement: false }, - "Double": { automatic: true, needsStatement: false }, + "Float": { automatic: true, needsStatement: true }, + "Double": { automatic: true, needsStatement: true }, } @@ -471,13 +455,6 @@ export class DoublePrimitiveType extends PrimitiveType { public castTo(value: Value, type: Type): Value { - if (type == stringPrimitiveType) { - return { - type: type, - value: "" + value.value - } - } - if (type == intPrimitiveType) { return { type: type, @@ -492,9 +469,12 @@ export class DoublePrimitiveType extends PrimitiveType { } } + public valueToString(value: Value): string { + return floatToString(value.value); } + public compute(operation: TokenType, firstOperand: Value, secondOperand?: Value): any { let value = (firstOperand.value); @@ -576,7 +556,6 @@ export class BooleanPrimitiveType extends PrimitiveType { }; this.canCastToMap = { - "String": { automatic: true, needsStatement: true }, "boolean": { automatic: true, needsStatement: false }, "Boolean": { automatic: true, needsStatement: false }, } @@ -590,12 +569,6 @@ export class BooleanPrimitiveType extends PrimitiveType { public castTo(value: Value, type: Type): Value { - if (type == stringPrimitiveType) { - return { - type: type, - value: "" + value.value - } - } } @@ -869,6 +842,8 @@ export class StringPrimitiveType extends Klass { } + public allowsNull(): boolean { return true; } + public debugOutput(value: Value): string { return '"' + value.value + '"'; } diff --git a/src/client/compiler/types/Types.ts b/src/client/compiler/types/Types.ts index 87b70ecf..5a620796 100644 --- a/src/client/compiler/types/Types.ts +++ b/src/client/compiler/types/Types.ts @@ -3,7 +3,7 @@ import { TextPosition, TokenType } from "../lexer/Token.js"; import { Module } from "../parser/Module.js"; import { Program } from "../parser/Program.js"; import { ArrayType } from "./Array.js"; -import { Visibility, TypeVariable } from "./Class.js"; +import { Visibility } from "./Class.js"; export type UsagePositions = Map; @@ -91,6 +91,12 @@ export abstract class PrimitiveType extends Type { return this.canCastToMap[type.identifier]; } + public allowsNull(): boolean { return false; } + + public valueToString(value: Value): string { + return "" + value.value; + } + } export class Attribute { diff --git a/src/client/interpreter/Interpreter.ts b/src/client/interpreter/Interpreter.ts index 7d00862f..eb6738e5 100644 --- a/src/client/interpreter/Interpreter.ts +++ b/src/client/interpreter/Interpreter.ts @@ -1,4 +1,4 @@ -import { TextPosition, TokenType } from "../compiler/lexer/Token.js"; +import { TextPosition, TokenType, TokenTypeReadable } from "../compiler/lexer/Token.js"; import { Module, ModuleStore } from "../compiler/parser/Module.js"; import { Program, Statement, ReturnStatement } from "../compiler/parser/Program.js"; import { ArrayType } from "../compiler/types/Array.js"; @@ -1364,7 +1364,10 @@ export class Interpreter { let text = null; let color = null; if (node.withColor) color = stack.pop().value; - if (!node.empty) text = stack.pop().value; + if (!node.empty) { + text = stack.pop().value; + if (text == null) text = "null"; + } if (node.type == TokenType.println) { this.printManager.println(text, color); } else { diff --git a/src/client/tools/StringTools.ts b/src/client/tools/StringTools.ts index 7818ef05..8c8c0ab9 100644 --- a/src/client/tools/StringTools.ts +++ b/src/client/tools/StringTools.ts @@ -62,4 +62,12 @@ export function formatAsJavadocComment(s: string, indent: number|string = ""): s if(s.length > 0) s = "\n" + s; s = indentString + "/**" + s.replace(/\n/g, "\n" + indentString + " * ") + "\n" + indentString + " */"; return s; +} + +export function nullToString(s: string) { + return s == null ? "null" : s; +} + +export function floatToString(val: number){ + return val + (Number.isInteger(val)? ".0": ""); } \ No newline at end of file From ec0a6e939b16b8fafddeabfa2b9714aadd1414f3 Mon Sep 17 00:00:00 2001 From: InformaTiger Date: Fri, 1 Jul 2022 17:44:08 +0200 Subject: [PATCH 03/12] UnboxableKlass --- src/client/compiler/types/Class.ts | 41 +++++++++++++------ .../compiler/types/boxedTypes/BooleanClass.ts | 6 +-- .../types/boxedTypes/CharacterClass.ts | 7 +--- .../compiler/types/boxedTypes/DoubleClass.ts | 9 ++-- .../compiler/types/boxedTypes/FloatClass.ts | 9 ++-- .../compiler/types/boxedTypes/IntegerClass.ts | 6 +-- .../compiler/types/boxedTypes/LongClass.ts | 6 +-- 7 files changed, 45 insertions(+), 39 deletions(-) diff --git a/src/client/compiler/types/Class.ts b/src/client/compiler/types/Class.ts index fb4a8229..79cd79eb 100644 --- a/src/client/compiler/types/Class.ts +++ b/src/client/compiler/types/Class.ts @@ -890,7 +890,7 @@ export class StaticClass extends Type { let attributes = this.getAttributes(Visibility.private); let object = this.classObject; - if(attributes == null) return "{}"; + if (attributes == null) return "{}"; for (let i = 0; i < attributes.length; i++) { @@ -913,13 +913,13 @@ export class StaticClass extends Type { let itemList: monaco.languages.CompletionItem[] = []; for (let attribute of this.getAttributes(visibilityUpTo)) { - + itemList.push({ label: attribute.identifier, //@ts-ignore - detail: attribute.color? attribute.color : undefined, + detail: attribute.color ? attribute.color : undefined, //@ts-ignore - kind: attribute.color? monaco.languages.CompletionItemKind.Color : monaco.languages.CompletionItemKind.Field, + kind: attribute.color ? monaco.languages.CompletionItemKind.Color : monaco.languages.CompletionItemKind.Field, insertText: attribute.identifier, range: rangeToReplace, documentation: attribute.documentation == null ? undefined : { @@ -1380,7 +1380,7 @@ function findSuitableMethods(methodList: Method[], identifier: string, parameter * Bei f.berührt(r) gibt es eine Variante mit Parametertyp String (schlecht!) und * eine mit Parametertyp Object. Letztere soll genommen werden, also: */ - if(mParameterType == stringPrimitiveType) howManyCastings += 0.5; + if (mParameterType == stringPrimitiveType) howManyCastings += 0.5; continue; } @@ -1407,13 +1407,13 @@ function findSuitableMethods(methodList: Method[], identifier: string, parameter if (givenType.canCastTo(mParameterTypeEllispsis)) { howManyCastings++; - /** - * Rechteck r; - * GNGFigur f; - * Bei f.berührt(r) gibt es eine Variante mit Parametertyp String (schlecht!) und - * eine mit Parametertyp Object. Letztere soll genommen werden, also: - */ - if(mParameterTypeEllispsis == stringPrimitiveType) howManyCastings += 0.5; + /** + * Rechteck r; + * GNGFigur f; + * Bei f.berührt(r) gibt es eine Variante mit Parametertyp String (schlecht!) und + * eine mit Parametertyp Object. Letztere soll genommen werden, also: + */ + if (mParameterTypeEllispsis == stringPrimitiveType) howManyCastings += 0.5; continue; } @@ -1487,3 +1487,20 @@ export function getVisibilityUpTo(objectType: Klass | StaticClass, currentClassC } + +export class UnboxableKlass extends Klass { + + public unboxableAs: Type[] = []; + + public castTo(value: Value, type: Type): Value { + if (! (type instanceof PrimitiveType)) return null; + if (this.unboxableAs.includes(type)) { + if (value.value == null && ! type.allowsNull()) throw Error("null kann nicht in einen primitiven " + type.identifier + " umgewandelt werden."); + else return { + value: value.value, + type: type + } + } + return null; + } +} \ No newline at end of file diff --git a/src/client/compiler/types/boxedTypes/BooleanClass.ts b/src/client/compiler/types/boxedTypes/BooleanClass.ts index 0d1c5766..94d677a5 100644 --- a/src/client/compiler/types/boxedTypes/BooleanClass.ts +++ b/src/client/compiler/types/boxedTypes/BooleanClass.ts @@ -1,12 +1,10 @@ import { RuntimeObject } from "../../../interpreter/RuntimeObject.js"; -import { Klass, Visibility } from "../Class.js"; +import { Klass, UnboxableKlass, Visibility } from "../Class.js"; import { booleanPrimitiveType, charPrimitiveType, intPrimitiveType, stringPrimitiveType } from "../PrimitiveTypes.js"; import { Method, Parameterlist, Type, Value, Attribute } from "../Types.js"; -export class BooleanClass extends Klass { - - unboxableAs = []; +export class BooleanClass extends UnboxableKlass { constructor(baseClass: Klass) { super("Boolean", null, "Wrapper-Klasse, um boolean-Werte in Collections verenden zu können."); diff --git a/src/client/compiler/types/boxedTypes/CharacterClass.ts b/src/client/compiler/types/boxedTypes/CharacterClass.ts index 5e2700e6..061c241b 100644 --- a/src/client/compiler/types/boxedTypes/CharacterClass.ts +++ b/src/client/compiler/types/boxedTypes/CharacterClass.ts @@ -1,12 +1,10 @@ import { RuntimeObject } from "../../../interpreter/RuntimeObject.js"; -import { Klass } from "../Class.js"; +import { Klass, UnboxableKlass } from "../Class.js"; import { booleanPrimitiveType, charPrimitiveType, intPrimitiveType, stringPrimitiveType } from "../PrimitiveTypes.js"; import { Method, Parameterlist, Type, Value } from "../Types.js"; -export class CharacterClass extends Klass { - - unboxableAs = []; +export class CharacterClass extends UnboxableKlass { constructor(baseClass: Klass) { super("Character", null, "Wrapper-Klasse, um char-Werte in Collections verenden zu können."); @@ -153,5 +151,4 @@ export class CharacterClass extends Klass { return "" + value.value; } - } diff --git a/src/client/compiler/types/boxedTypes/DoubleClass.ts b/src/client/compiler/types/boxedTypes/DoubleClass.ts index 11bd1703..3b350d3a 100644 --- a/src/client/compiler/types/boxedTypes/DoubleClass.ts +++ b/src/client/compiler/types/boxedTypes/DoubleClass.ts @@ -1,12 +1,11 @@ -import { Klass, Visibility } from "../Class.js"; +import { Klass, UnboxableKlass, Visibility } from "../Class.js"; import { Method, Parameterlist, Attribute, Value, Type, PrimitiveType } from "../Types.js"; import { intPrimitiveType, stringPrimitiveType, floatPrimitiveType, doublePrimitiveType, booleanPrimitiveType } from "../PrimitiveTypes.js"; import { RuntimeObject } from "../../../interpreter/RuntimeObject.js"; +import { floatToString } from "../../../tools/StringTools.js"; -export class DoubleClass extends Klass { - - unboxableAs = []; +export class DoubleClass extends UnboxableKlass { constructor(baseClass: Klass) { super("Double", null, "Wrapper-Klasse, um double-Werte in Collections verenden zu können."); @@ -87,7 +86,7 @@ export class DoubleClass extends Klass { this.addMethod(new Method("toString", new Parameterlist([ ]), stringPrimitiveType, (parameters) => { - return "" + parameters[0].value; + return floatToString(parameters[0].value); }, false, false, "Gibt den Wert des Objekts als String-Wert zurück.")); this.addMethod(new Method("hashCode", new Parameterlist([ diff --git a/src/client/compiler/types/boxedTypes/FloatClass.ts b/src/client/compiler/types/boxedTypes/FloatClass.ts index f4c4565b..02868eb3 100644 --- a/src/client/compiler/types/boxedTypes/FloatClass.ts +++ b/src/client/compiler/types/boxedTypes/FloatClass.ts @@ -1,12 +1,11 @@ -import { Klass, Visibility } from "../Class.js"; +import { Klass, UnboxableKlass, Visibility } from "../Class.js"; import { Method, Parameterlist, Attribute, Value, Type, PrimitiveType } from "../Types.js"; import { intPrimitiveType, stringPrimitiveType, doublePrimitiveType, floatPrimitiveType, booleanPrimitiveType } from "../PrimitiveTypes.js"; import { RuntimeObject } from "../../../interpreter/RuntimeObject.js"; +import { floatToString } from "../../../tools/StringTools.js"; -export class FloatClass extends Klass { - - unboxableAs = []; +export class FloatClass extends UnboxableKlass { constructor(baseClass: Klass) { super("Float", null, "Wrapper-Klasse, um float-Werte in Collections verenden zu können."); @@ -87,7 +86,7 @@ export class FloatClass extends Klass { this.addMethod(new Method("toString", new Parameterlist([ ]), stringPrimitiveType, (parameters) => { - return "" + parameters[0].value; + return floatToString(parameters[0].value); }, false, false, "Gibt den Wert des Objekts als String-Wert zurück.")); this.addMethod(new Method("hashCode", new Parameterlist([ diff --git a/src/client/compiler/types/boxedTypes/IntegerClass.ts b/src/client/compiler/types/boxedTypes/IntegerClass.ts index 99759d75..98c3de06 100644 --- a/src/client/compiler/types/boxedTypes/IntegerClass.ts +++ b/src/client/compiler/types/boxedTypes/IntegerClass.ts @@ -1,12 +1,10 @@ -import { Klass, Visibility } from "../Class.js"; +import { Klass, UnboxableKlass, Visibility } from "../Class.js"; import { Method, Parameterlist, Attribute, Value, Type, PrimitiveType } from "../Types.js"; import { intPrimitiveType, stringPrimitiveType, doublePrimitiveType, floatPrimitiveType, booleanPrimitiveType } from "../PrimitiveTypes.js"; import { RuntimeObject } from "../../../interpreter/RuntimeObject.js"; -export class IntegerClass extends Klass { - - unboxableAs = []; +export class IntegerClass extends UnboxableKlass { constructor(baseClass: Klass) { super("Integer", null, "Wrapper-Klasse, um int-Werte in Collections verenden zu können."); diff --git a/src/client/compiler/types/boxedTypes/LongClass.ts b/src/client/compiler/types/boxedTypes/LongClass.ts index edf0614f..8c5100af 100644 --- a/src/client/compiler/types/boxedTypes/LongClass.ts +++ b/src/client/compiler/types/boxedTypes/LongClass.ts @@ -1,12 +1,10 @@ -import { Klass, Visibility } from "../Class.js"; +import { Klass, UnboxableKlass, Visibility } from "../Class.js"; import { Method, Parameterlist, Attribute, Value, Type, PrimitiveType } from "../Types.js"; import { longPrimitiveType, stringPrimitiveType, doublePrimitiveType, floatPrimitiveType, intPrimitiveType, booleanPrimitiveType } from "../PrimitiveTypes.js"; import { RuntimeObject } from "../../../interpreter/RuntimeObject.js"; -export class LongClass extends Klass { - - unboxableAs = []; +export class LongClass extends UnboxableKlass { constructor(baseClass: Klass) { super("Long", null, "Wrapper-Klasse, um int-Werte in Collections verenden zu können."); From 5d4b55aa620d333028a27f180b6b10ab38f963c3 Mon Sep 17 00:00:00 2001 From: InformaTiger Date: Fri, 1 Jul 2022 17:48:05 +0200 Subject: [PATCH 04/12] casting --- src/client/compiler/parser/CodeGenerator.ts | 182 ++++++++++---------- src/client/compiler/types/PrimitiveTypes.ts | 96 +++++++---- src/client/interpreter/Interpreter.ts | 31 +++- 3 files changed, 170 insertions(+), 139 deletions(-) diff --git a/src/client/compiler/parser/CodeGenerator.ts b/src/client/compiler/parser/CodeGenerator.ts index b62e0b65..714c5b3b 100644 --- a/src/client/compiler/parser/CodeGenerator.ts +++ b/src/client/compiler/parser/CodeGenerator.ts @@ -817,40 +817,37 @@ export class CodeGenerator { } - ensureAutomaticCasting(typeFrom: Type, typeTo: Type, position?: TextPosition, nodeFrom?: ASTNode): boolean { + ensureAutomaticCasting(typeFrom: Type, typeTo: Type, position?: TextPosition, nodeFrom?: ASTNode, nullTypeForbidden: boolean = false): boolean { if (typeFrom == null || typeTo == null) return false; - if (typeFrom.equals(typeTo)) { - return true; - } - - if (!typeFrom.canCastTo(typeTo)) { - - if (typeTo == booleanPrimitiveType && nodeFrom != null) { - - this.checkIfAssignmentInstedOfEqual(nodeFrom); + if (!(typeFrom == nullType && nullTypeForbidden)) { + if (typeFrom.equals(typeTo)) { + return true; } + if (!typeFrom.canCastTo(typeTo)) { - return false; - } + if (typeTo == booleanPrimitiveType && nodeFrom != null) { - if (typeFrom["unboxableAs"] != null && typeFrom["unboxableAs"].indexOf(typeTo) >= 0) { - return true; - } + this.checkIfAssignmentInstedOfEqual(nodeFrom); - if (typeFrom instanceof Klass && typeTo == stringPrimitiveType) { + } - let toStringStatement = this.getToStringStatement(typeFrom, position); - if (toStringStatement != null) { - this.pushStatements(toStringStatement); + return false; + } + + if (typeFrom["unboxableAs"] != null && typeFrom["unboxableAs"].indexOf(typeTo) >= 0) { + this.pushStatements({ + type: TokenType.castValue, + position: position, + newType: typeTo + }); return true; } - return false; } @@ -1327,38 +1324,7 @@ export class CodeGenerator { if (typeFrom.canCastTo(typeTo)) { - if (typeFrom instanceof PrimitiveType && typeTo instanceof PrimitiveType) { - let castInfo = typeFrom.getCastInformation(typeTo); - if (castInfo.needsStatement) { - this.pushStatements({ - type: TokenType.castValue, - position: node.position, - newType: typeTo - }); - } - } else if (typeFrom instanceof Klass && typeTo == stringPrimitiveType) { - let toStringMethod = typeFrom.getMethodBySignature("toString()"); - if (toStringMethod != null && toStringMethod.getReturnType() == stringPrimitiveType) { - - this.pushStatements({ - type: TokenType.callMethod, - position: node.position, - method: toStringMethod, - isSuperCall: false, - stackframeBegin: -1, - stepFinished: false - }); - - } else { - this.pushError("Der Datentyp " + typeFrom.identifier + " kann (zumindest durch casting) nicht in den Datentyp " + typeTo.identifier + " umgewandelt werden.", node.position); - this.pushStatements({ - type: TokenType.castValue, - position: node.position, - newType: typeTo - }); - } - - } + this.pushCastToStatement(typeFrom, typeTo, node); return { isAssignable: typeFrom1.isAssignable, @@ -1367,6 +1333,15 @@ export class CodeGenerator { } + if (typeFrom instanceof UnboxableKlass) { + for (let unboxableAs of typeFrom.unboxableAs) { + if (unboxableAs.canCastTo(typeTo)) { + this.pushCastToStatement(typeFrom, unboxableAs, node); + this.pushCastToStatement(unboxableAs, typeTo, node); + } + } + } + if ((typeFrom instanceof Klass || typeFrom instanceof Interface) && (typeTo instanceof Klass || typeTo instanceof Interface)) // if (typeFrom instanceof Klass && @@ -1394,6 +1369,17 @@ export class CodeGenerator { } + pushCastToStatement(typeFrom: Type, typeTo: Type, node: CastManuallyNode) { + let needsStatement: boolean = typeFrom != typeTo; + + if (needsStatement) this.pushStatements({ + type: TokenType.castValue, + position: node.position, + newType: typeTo + }); + + } + processPrint(node: PrintNode): StackType { let type = node.type == TokenType.keywordPrint ? TokenType.print : TokenType.println; @@ -1791,7 +1777,7 @@ export class CodeGenerator { } - if(switchStatement.defaultDestination == null){ + if (switchStatement.defaultDestination == null) { withReturnStatement = false; } @@ -1918,7 +1904,7 @@ export class CodeGenerator { kind = "userDefinedIterable"; } let iterableInterface = collectionType.getImplementedInterface("Iterable"); - if(collectionType.typeVariables.length == 0){ + if (collectionType.typeVariables.length == 0) { collectionElementType = objectType; } else { collectionElementType = collectionType.typeVariables[0].type; @@ -2140,11 +2126,11 @@ export class CodeGenerator { this.openBreakScope(); this.openContinueScope(); - let pc = this.currentProgram.statements.length; + let pc = this.currentProgram.statements.length; let statements = this.generateStatements(node.statements); let withReturnStatement = statements.withReturnStatement; - if(this.currentProgram.statements.length == pc){ + if (this.currentProgram.statements.length == pc) { this.insertNoOp(node.scopeTo, false); } @@ -2161,7 +2147,7 @@ export class CodeGenerator { } - insertNoOp(position: TextPosition, stepFinished: boolean){ + insertNoOp(position: TextPosition, stepFinished: boolean) { this.pushStatements({ type: TokenType.noOp, position: position, @@ -2180,11 +2166,11 @@ export class CodeGenerator { this.openBreakScope(); this.openContinueScope(); - let pc = this.currentProgram.statements.length; + let pc = this.currentProgram.statements.length; let statements = this.generateStatements(node.statements); let withReturnStatement = statements.withReturnStatement; - if(this.currentProgram.statements.length == pc){ + if (this.currentProgram.statements.length == pc) { this.insertNoOp(node.scopeTo, false); } @@ -3073,43 +3059,43 @@ export class CodeGenerator { } } - let isSystemMethod: boolean = false; + let isSystemMethod: boolean = false; if (method.isStatic && objectNode.type != null && - (objectNode.type instanceof StaticClass)){ - let classIdentifier = objectNode.type.Klass.identifier; + (objectNode.type instanceof StaticClass)) { + let classIdentifier = objectNode.type.Klass.identifier; - switch (classIdentifier) { - case "Input": - this.pushStatements({ - type: TokenType.callInputMethod, - method: method, + switch (classIdentifier) { + case "Input": + this.pushStatements({ + type: TokenType.callInputMethod, + method: method, + position: node.position, + stepFinished: true, + stackframeBegin: -(parameterTypes.length + 1 + stackframeDelta) // this-object followed by parameters + }); + isSystemMethod = true; + break; + case "SystemTools": + case "Robot": + if (["pause", "warten"].indexOf(method.identifier) >= 0) { + this.pushStatements([{ + type: TokenType.setPauseDuration, position: node.position, - stepFinished: true, - stackframeBegin: -(parameterTypes.length + 1 + stackframeDelta) // this-object followed by parameters - }); - isSystemMethod = true; - break; - case "SystemTools": - case "Robot": - if(["pause", "warten"].indexOf(method.identifier) >= 0){ - this.pushStatements([{ - type: TokenType.setPauseDuration, - position: node.position, - stepFinished: true - },{ - type: TokenType.pause, - position: node.position, - stepFinished: true - } - ]); - isSystemMethod = true; + stepFinished: true + }, { + type: TokenType.pause, + position: node.position, + stepFinished: true } - break; - } - + ]); + isSystemMethod = true; + } + break; } - if(!isSystemMethod) { + } + + if (!isSystemMethod) { this.pushStatements({ type: TokenType.callMethod, method: method, @@ -3191,7 +3177,7 @@ export class CodeGenerator { let convertedLeftType = leftType.type; if (isAssignment) { - if (!this.ensureAutomaticCasting(rightType.type, leftType.type, node.position, node.firstOperand)) { + if (!this.ensureAutomaticCasting(rightType.type, leftType.type, node.position, node.firstOperand, true)) { this.pushError("Der Wert vom Datentyp " + rightType.type.identifier + " auf der rechten Seite kann der Variablen auf der linken Seite (Datentyp " + leftType.type.identifier + ") nicht zugewiesen werden.", node.position); return leftType; } @@ -3250,8 +3236,16 @@ export class CodeGenerator { for (let rt of rightTypes) { resultType = lt.getResultType(node.operator, rt); if (resultType != null) { - leftType.type = lt; - rightType.type = rt; + this.insertStatements(programPosAfterLeftOpoerand, { + type: TokenType.castValue, + position: node.firstOperand.position, + newType: lt + }); + this.pushStatements({ + type: TokenType.castValue, + position: node.secondOperand.position, + newType: rt + }); convertedLeftType = lt; break; } @@ -3318,7 +3312,7 @@ export class CodeGenerator { if (leftType == null) return; - if (this.ensureAutomaticCasting(leftType.type, booleanPrimitiveType, null, node.firstOperand)) { + if (this.ensureAutomaticCasting(leftType.type, booleanPrimitiveType, null, node.firstOperand, true)) { let secondOperand = node.secondOperand; if (secondOperand != null) { diff --git a/src/client/compiler/types/PrimitiveTypes.ts b/src/client/compiler/types/PrimitiveTypes.ts index 236e50da..586a13d4 100644 --- a/src/client/compiler/types/PrimitiveTypes.ts +++ b/src/client/compiler/types/PrimitiveTypes.ts @@ -28,7 +28,10 @@ export class NullType extends Type { return (type instanceof Klass || type instanceof Interface || type instanceof ArrayType); } castTo(value: Value, type: Type) { - return value; + return { + value: value.value, + type: type + }; } equals(type: Type) { return (type instanceof Klass || type instanceof Interface); @@ -77,7 +80,7 @@ export class IntPrimitiveType extends PrimitiveType { this.description = "ganze Zahl" this.operationTable = { - [TokenType.plus]: { "long": longPrimitiveType, "Long": longPrimitiveType, "int": intPrimitiveType, "Integer": intPrimitiveType, "float": floatPrimitiveType, "Float": floatPrimitiveType, "double": doublePrimitiveType, "Double": doublePrimitiveType, "String": stringPrimitiveType }, + [TokenType.plus]: { "long": longPrimitiveType, "Long": longPrimitiveType, "int": intPrimitiveType, "Integer": intPrimitiveType, "float": floatPrimitiveType, "Float": floatPrimitiveType, "double": doublePrimitiveType, "Double": doublePrimitiveType }, [TokenType.minus]: { "none": intPrimitiveType, "long": longPrimitiveType, "Long": longPrimitiveType, "int": intPrimitiveType, "Integer": intPrimitiveType, "float": floatPrimitiveType, "Float": floatPrimitiveType, "double": doublePrimitiveType, "Double": doublePrimitiveType }, [TokenType.multiplication]: { "long": longPrimitiveType, "Long": longPrimitiveType, "int": intPrimitiveType, "Integer": intPrimitiveType, "float": floatPrimitiveType, "Float": floatPrimitiveType, "double": doublePrimitiveType, "Double": doublePrimitiveType }, [TokenType.modulo]: { "long": longPrimitiveType, "Long": longPrimitiveType, "int": intPrimitiveType, "Integer": intPrimitiveType }, @@ -111,7 +114,7 @@ export class IntPrimitiveType extends PrimitiveType { "char": { automatic: true, needsStatement: true }, "int": { automatic: true, needsStatement: false }, "long": { automatic: true, needsStatement: false }, - "Integer": { automatic: true, needsStatement: false }, + "Integer": { automatic: true, needsStatement: true }, } @@ -123,12 +126,6 @@ export class IntPrimitiveType extends PrimitiveType { public castTo(value: Value, type: Type): Value { - if (type == floatPrimitiveType || type == doublePrimitiveType) { - return { - type: type, - value: value.value - }; - } if (type == charPrimitiveType) { return { type: type, @@ -240,7 +237,7 @@ export class LongPrimitiveType extends IntPrimitiveType { this.description = "ganze Zahl" this.operationTable = { - [TokenType.plus]: { "long": longPrimitiveType, "int": longPrimitiveType, "Long": longPrimitiveType, "Integer": longPrimitiveType, "float": floatPrimitiveType, "Float": floatPrimitiveType, "double": doublePrimitiveType, "Double": doublePrimitiveType, "String": stringPrimitiveType }, + [TokenType.plus]: { "long": longPrimitiveType, "int": longPrimitiveType, "Long": longPrimitiveType, "Integer": longPrimitiveType, "float": floatPrimitiveType, "Float": floatPrimitiveType, "double": doublePrimitiveType, "Double": doublePrimitiveType }, [TokenType.minus]: { "none": intPrimitiveType, "long": longPrimitiveType, "int": longPrimitiveType, "Long": longPrimitiveType, "Integer": longPrimitiveType, "float": floatPrimitiveType, "Float": floatPrimitiveType, "double": doublePrimitiveType, "Double": doublePrimitiveType }, [TokenType.multiplication]: { "long": longPrimitiveType, "int": longPrimitiveType, "Long": longPrimitiveType, "Integer": longPrimitiveType, "float": floatPrimitiveType, "Float": floatPrimitiveType, "double": doublePrimitiveType, "Double": doublePrimitiveType }, [TokenType.modulo]: { "long": longPrimitiveType, "int": longPrimitiveType, "Long": longPrimitiveType, "Integer": longPrimitiveType }, @@ -298,7 +295,7 @@ export class FloatPrimitiveType extends PrimitiveType { this.description = "Fließkommazahl mit einfacher Genauigkeit" this.operationTable = { - [TokenType.plus]: { "Integer": floatPrimitiveType, "int": floatPrimitiveType, "float": floatPrimitiveType, "Float": floatPrimitiveType, "double": doublePrimitiveType, "Double": doublePrimitiveType, "String": stringPrimitiveType }, + [TokenType.plus]: { "Integer": floatPrimitiveType, "int": floatPrimitiveType, "float": floatPrimitiveType, "Float": floatPrimitiveType, "double": doublePrimitiveType, "Double": doublePrimitiveType }, [TokenType.minus]: { "none": floatPrimitiveType, "Integer": floatPrimitiveType, "int": floatPrimitiveType, "float": floatPrimitiveType, "Float": floatPrimitiveType, "double": doublePrimitiveType, "Double": doublePrimitiveType }, [TokenType.multiplication]: { "Integer": floatPrimitiveType, "int": floatPrimitiveType, "float": floatPrimitiveType, "Float": floatPrimitiveType, "double": doublePrimitiveType, "Double": doublePrimitiveType }, [TokenType.division]: { "Integer": floatPrimitiveType, "int": floatPrimitiveType, "float": floatPrimitiveType, "Float": floatPrimitiveType, "double": doublePrimitiveType, "Double": doublePrimitiveType }, @@ -338,12 +335,14 @@ export class FloatPrimitiveType extends PrimitiveType { } } - if (type == doublePrimitiveType) { - return { - type: type, - value: value.value - } - } + // if (type == doublePrimitiveType || type == DoubleType || type == FloatType) { + // return { + // type: type, + // value: value.value + // } + // } + + } public valueToString(value: Value): string { return floatToString(value.value); @@ -422,7 +421,7 @@ export class DoublePrimitiveType extends PrimitiveType { this.description = "Fließkommazahl mit doppelter Genauigkeit" this.operationTable = { - [TokenType.plus]: { "int": doublePrimitiveType, "Integer": doublePrimitiveType, "float": doublePrimitiveType, "Float": doublePrimitiveType, "double": doublePrimitiveType, "Double": doublePrimitiveType, "String": stringPrimitiveType }, + [TokenType.plus]: { "int": doublePrimitiveType, "Integer": doublePrimitiveType, "float": doublePrimitiveType, "Float": doublePrimitiveType, "double": doublePrimitiveType, "Double": doublePrimitiveType }, [TokenType.minus]: { "none": doublePrimitiveType, "int": doublePrimitiveType, "Integer": doublePrimitiveType, "float": doublePrimitiveType, "Float": doublePrimitiveType, "double": doublePrimitiveType, "Double": doublePrimitiveType }, [TokenType.multiplication]: { "int": doublePrimitiveType, "Integer": doublePrimitiveType, "float": doublePrimitiveType, "Float": doublePrimitiveType, "double": doublePrimitiveType, "Double": doublePrimitiveType }, [TokenType.division]: { "int": doublePrimitiveType, "Integer": doublePrimitiveType, "float": doublePrimitiveType, "Float": doublePrimitiveType, "double": doublePrimitiveType, "Double": doublePrimitiveType }, @@ -462,12 +461,7 @@ export class DoublePrimitiveType extends PrimitiveType { } } - if (type == floatPrimitiveType) { - return { - type: type, - value: value.value - } - } + } public valueToString(value: Value): string { return floatToString(value.value); @@ -547,7 +541,7 @@ export class BooleanPrimitiveType extends PrimitiveType { this.description = "boolescher Wert (true oder false)" this.operationTable = { - [TokenType.plus]: { "String": stringPrimitiveType }, + [TokenType.plus]: {}, [TokenType.and]: { "boolean": booleanPrimitiveType }, [TokenType.or]: { "boolean": booleanPrimitiveType }, [TokenType.not]: { "none": booleanPrimitiveType }, @@ -557,7 +551,7 @@ export class BooleanPrimitiveType extends PrimitiveType { this.canCastToMap = { "boolean": { automatic: true, needsStatement: false }, - "Boolean": { automatic: true, needsStatement: false }, + "Boolean": { automatic: true, needsStatement: true }, } @@ -569,6 +563,7 @@ export class BooleanPrimitiveType extends PrimitiveType { public castTo(value: Value, type: Type): Value { + return undefined; } @@ -579,7 +574,7 @@ export class BooleanPrimitiveType extends PrimitiveType { switch (operation) { case TokenType.plus: - return value + (secondOperand.value); + return value + nullToString((secondOperand.value)); case TokenType.equal: return value == (secondOperand.value); @@ -688,9 +683,9 @@ export class StringPrimitiveType extends Klass { init() { this.operationTable = { [TokenType.plus]: { - "String": stringPrimitiveType, "int": stringPrimitiveType, - "float": stringPrimitiveType, "double": doublePrimitiveType, - "boolean": stringPrimitiveType, "char": stringPrimitiveType + "String": stringPrimitiveType //, "int": stringPrimitiveType, + // "float": stringPrimitiveType, "double": stringPrimitiveType, + // "boolean": stringPrimitiveType, "char": stringPrimitiveType }, [TokenType.equal]: { "String": booleanPrimitiveType, "null": booleanPrimitiveType }, [TokenType.notEqual]: { "String": booleanPrimitiveType, "null": booleanPrimitiveType }, @@ -802,14 +797,17 @@ export class StringPrimitiveType extends Klass { let value = (firstOperand.value); + let err: Error = checkNotNull(operation, this, firstOperand, secondOperand, [TokenType.plus, TokenType.keywordInstanceof]) + if (err != null) return err; + switch (operation) { case TokenType.plus: if (secondOperand.type == stringPrimitiveType || secondOperand.type == charPrimitiveType) { - return value + (secondOperand.value); + return nullToString(value) + (secondOperand.value); // because null + null = 0 in javascript } else if (secondOperand.type == booleanPrimitiveType) { - return value + (secondOperand.value); + return nullToString(value) + (secondOperand.value); } else { - return value + (secondOperand.value); + return nullToString(value) + (secondOperand.value); } case TokenType.lower: @@ -877,9 +875,9 @@ export class CharPrimitiveType extends PrimitiveType { "int": { automatic: true, needsStatement: true }, "float": { automatic: true, needsStatement: true }, "double": { automatic: true, needsStatement: true }, - "String": { automatic: true, needsStatement: false }, + "String": { automatic: true, needsStatement: true }, "char": { automatic: true, needsStatement: false }, - "Character": { automatic: true, needsStatement: false }, + "Character": { automatic: true, needsStatement: true }, } } @@ -890,9 +888,15 @@ export class CharPrimitiveType extends PrimitiveType { public castTo(value: Value, type: Type): Value { - if (type == stringPrimitiveType) { - return value; - } + // let unboxed = this.unboxFrom(value, type); + // if (unboxed != null) return unboxed; + + // if (type == stringPrimitiveType || type == CharacterType) { + // return { + // type: type, + // value: value + // } + // } if (type == intPrimitiveType || type == floatPrimitiveType || type == doublePrimitiveType) { return { @@ -969,4 +973,20 @@ export var TokenTypeToDataTypeMap: { [tt: number]: Type } = { [TokenType.stringConstant]: stringPrimitiveType, [TokenType.charConstant]: charPrimitiveType, [TokenType.keywordNull]: nullType +} + + +function checkNotNull(operation: TokenType, type: Type, firstOperand: Value, secondOperand?: Value, nullAllowedFor: TokenType[] = []): Error { + if ((firstOperand.value == null || secondOperand.value == null) && !nullAllowedFor.concat([TokenType.equal, TokenType.notEqual]).includes(operation)) { + let typeAndNull: (v: Value) => string = (v: Value) => v.value == null ? "(" + type.identifier + ")" + " null" : type.identifier; + return new OperandIsNull("Unerlaubte Rechnung mit null: " + typeAndNull(firstOperand) + " " + TokenTypeReadable[operation] + " " + typeAndNull(secondOperand)); + } + return null; +} + +export class OperandIsNull extends Error { + constructor(message?: string) { + super(message); + this.name = "OperandIsNullError"; + } } \ No newline at end of file diff --git a/src/client/interpreter/Interpreter.ts b/src/client/interpreter/Interpreter.ts index eb6738e5..c489d6a9 100644 --- a/src/client/interpreter/Interpreter.ts +++ b/src/client/interpreter/Interpreter.ts @@ -678,7 +678,7 @@ export class Interpreter { this.worldHelper.cacheAsBitmap(); } - this.databaseConnectionHelpers.forEach((ch)=> ch.close()); + this.databaseConnectionHelpers.forEach((ch) => ch.close()); this.databaseConnectionHelpers = []; this.heap = {}; @@ -833,7 +833,17 @@ export class Interpreter { case TokenType.castValue: let relPos = node.stackPosRelative == null ? 0 : node.stackPosRelative; value = stack[stackTop + relPos]; - stack[stackTop + relPos] = value.type.castTo(value, node.newType); + try { + let casted = value.type.castTo(value, node.newType); + if (casted == undefined) casted = { + value: value.value, + type: node.newType + } + stack[stackTop + relPos] = casted; + } catch (err) { + if (err.message) return err.message; + else return "Bei dem Casten von " + value.type.identifier + " zu " + node.newType.identifier + " trat ein Fehler auf: " + err.name + "."; + } break; case TokenType.checkCast: value = stack[stackTop]; @@ -952,6 +962,13 @@ export class Interpreter { let secondOperand = stack.pop(); let resultValue = node.leftType.compute(node.operator, stack[stackTop - 1], secondOperand); + if (resultValue instanceof Error) { + if (resultValue.message) return resultValue.message; + else "Bei der Berechnung von " + stack[stackTop - 1].type.identifier + " " + + TokenTypeReadable[node.operator] + " " + secondOperand.type.identifier + + " trat ein Fehler (" + resultValue.name + ") auf." + + } let resultType = node.leftType.getResultType(node.operator, secondOperand.type); stack[stackTop - 1] = { type: resultType, @@ -1463,7 +1480,7 @@ export class Interpreter { } oldState: InterpreterState; - pauseForInput(){ + pauseForInput() { this.timerStopped = true; this.additionalStepFinishedFlag = true; this.oldState = this.state; @@ -1471,9 +1488,9 @@ export class Interpreter { this.showProgramPointerAndVariables(); } - resumeAfterInput(value: Value, popPriorValue: boolean = false){ - if(popPriorValue) this.stack.pop(); - if(value != null) this.stack.push(value); + resumeAfterInput(value: Value, popPriorValue: boolean = false) { + if (popPriorValue) this.stack.pop(); + if (value != null) this.stack.push(value); this.main.hideProgramPointerPosition(); this.setState(InterpreterState.paused); if (this.oldState == InterpreterState.running) { @@ -1867,7 +1884,7 @@ export class Interpreter { } registerDatabaseConnection(ch: ConnectionHelper) { - this.databaseConnectionHelpers.push(ch); + this.databaseConnectionHelpers.push(ch); } From c6fb6422c785ed933bcf820f1d7ad88b5f1f84ee Mon Sep 17 00:00:00 2001 From: InformaTiger Date: Fri, 1 Jul 2022 21:06:55 +0200 Subject: [PATCH 05/12] allow == and !== for null --- src/client/compiler/types/PrimitiveTypes.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/client/compiler/types/PrimitiveTypes.ts b/src/client/compiler/types/PrimitiveTypes.ts index 586a13d4..70ac23e5 100644 --- a/src/client/compiler/types/PrimitiveTypes.ts +++ b/src/client/compiler/types/PrimitiveTypes.ts @@ -19,9 +19,12 @@ export class NullType extends Type { } getResultType(operation: TokenType, secondOperandType: Type) { - return null; + if (operation == TokenType.equal || operation == TokenType.notEqual) return secondOperandType.getResultType(operation,this); } compute(operation: TokenType, firstOperand: Value, secondOperand: Value) { + if (operation == TokenType.equal || operation == TokenType.notEqual) { + return (firstOperand.value == secondOperand.value) == (operation == TokenType.equal); + } return null; } canCastTo(type: Type) { From b78587755b1c76432076a748513755f996bba8bf Mon Sep 17 00:00:00 2001 From: InformaTiger Date: Fri, 1 Jul 2022 22:16:09 +0200 Subject: [PATCH 06/12] allow Color-objects as parameters --- src/client/runtimelibrary/graphics/Bitmap.ts | 117 +++++++++++-- .../runtimelibrary/graphics/FilledShape.ts | 161 ++++++++++++++++-- .../graphics/FilledShapeDefaults.ts | 18 +- src/client/runtimelibrary/graphics/Shape.ts | 23 ++- src/client/runtimelibrary/graphics/World.ts | 22 ++- 5 files changed, 301 insertions(+), 40 deletions(-) diff --git a/src/client/runtimelibrary/graphics/Bitmap.ts b/src/client/runtimelibrary/graphics/Bitmap.ts index 2fa1f462..9a5d5ca2 100644 --- a/src/client/runtimelibrary/graphics/Bitmap.ts +++ b/src/client/runtimelibrary/graphics/Bitmap.ts @@ -135,6 +135,42 @@ export class BitmapClass extends Klass { }, false, false, 'Setzt die Farbe des Pixels bei (x, y). Die Farbe ist entweder eine vordefinierte Farbe (Color.black, Color.red, ...) oder eine css-Farbe der Art "#ffa7b3" (ohne alpha), "#ffa7b380" (mit alpha), "rgb(172, 22, 18)" oder "rgba(123, 22,18, 0.3)". 0.0 <= alpha <= 1.0.', false)); + this.addMethod(new Method("setColor", new Parameterlist([ + { identifier: "x", type: intPrimitiveType, declaration: null, usagePositions: null, isFinal: true }, + { identifier: "y", type: intPrimitiveType, declaration: null, usagePositions: null, isFinal: true }, + { identifier: "color", type: colorType, declaration: null, usagePositions: null, isFinal: true }, + ]), voidPrimitiveType, + (parameters) => { + + let o: RuntimeObject = parameters[0].value; + let x: number = parameters[1].value; + let y: number = parameters[2].value; + let color: string = parameters[3].value; + let sh: BitmapHelperNew = o.intrinsicData["Actor"]; + + sh.setzeFarbe(x, y, color); + + }, false, false, 'Setzt die Farbe des Pixels bei (x, y). Die Farbe ist entweder eine vordefinierte Farbe (Color.black, Color.red, ...) oder eine css-Farbe der Art "#ffa7b3" (ohne alpha), "#ffa7b380" (mit alpha), "rgb(172, 22, 18)" oder "rgba(123, 22,18, 0.3)"', false)); + + this.addMethod(new Method("setColor", new Parameterlist([ + { identifier: "x", type: intPrimitiveType, declaration: null, usagePositions: null, isFinal: true }, + { identifier: "y", type: intPrimitiveType, declaration: null, usagePositions: null, isFinal: true }, + { identifier: "color", type: colorType, declaration: null, usagePositions: null, isFinal: true }, + { identifier: "alpha", type: doublePrimitiveType, declaration: null, usagePositions: null, isFinal: true }, + ]), voidPrimitiveType, + (parameters) => { + + let o: RuntimeObject = parameters[0].value; + let x: number = parameters[1].value; + let y: number = parameters[2].value; + let color: string = parameters[3].value; + let alpha: number = parameters[4].value; + let sh: BitmapHelperNew = o.intrinsicData["Actor"]; + + sh.setzeFarbe(x, y, color, alpha); + + }, false, false, 'Setzt die Farbe des Pixels bei (x, y). Die Farbe ist entweder eine vordefinierte Farbe (Color.black, Color.red, ...) oder eine css-Farbe der Art "#ffa7b3" (ohne alpha), "#ffa7b380" (mit alpha), "rgb(172, 22, 18)" oder "rgba(123, 22,18, 0.3)". 0.0 <= alpha <= 1.0.', false)); + this.addMethod(new Method("isColor", new Parameterlist([ { identifier: "x", type: intPrimitiveType, declaration: null, usagePositions: null, isFinal: true }, { identifier: "y", type: intPrimitiveType, declaration: null, usagePositions: null, isFinal: true }, @@ -169,6 +205,23 @@ export class BitmapClass extends Klass { }, false, false, 'Gibt genau dann true zurück, wenn das Pixel bei (x, y) die angegebene Farbe besitzt. Die Farbe wird als int-Wert gegeben, wobei farbe == 255*255*rot + 255*grün + blau und 0.0 <= alpha <= 1.0', false)); + this.addMethod(new Method("isColor", new Parameterlist([ + { identifier: "x", type: intPrimitiveType, declaration: null, usagePositions: null, isFinal: true }, + { identifier: "y", type: intPrimitiveType, declaration: null, usagePositions: null, isFinal: true }, + { identifier: "color", type: colorType, declaration: null, usagePositions: null, isFinal: true } + ]), booleanPrimitiveType, + (parameters) => { + + let o: RuntimeObject = parameters[0].value; + let x: number = parameters[1].value; + let y: number = parameters[2].value; + let color: RuntimeObject = parameters[3].value; + let sh: BitmapHelperNew = o.intrinsicData["Actor"]; + + return sh.istFarbe(x, y, color); + + }, false, false, 'Gibt genau dann true zurück, wenn das Pixel bei (x, y) die angegebene Farbe besitzt. Die Farbe wird als int-Wert gegeben, wobei farbe == 255*255*rot + 255*grün + blau und 0.0 <= alpha <= 1.0', false)); + this.addMethod(new Method("fillAll", new Parameterlist([ { identifier: "color", type: intPrimitiveType, declaration: null, usagePositions: null, isFinal: true }, @@ -185,6 +238,22 @@ export class BitmapClass extends Klass { }, false, false, 'Füllt die ganze Bitmap mit einer Farbe. Die Farbe wird als int-Wert gegeben, wobei farbe == 255*255*rot + 255*grün + blau und 0.0 <= alpha <= 1.0', false)); + this.addMethod(new Method("fillAll", new Parameterlist([ + { identifier: "color", type: colorType, declaration: null, usagePositions: null, isFinal: true }, + { identifier: "alpha", type: doublePrimitiveType, declaration: null, usagePositions: null, isFinal: true }, + ]), voidPrimitiveType, + (parameters) => { + + let o: RuntimeObject = parameters[0].value; + let color: RuntimeObject = parameters[1].value; + let alpha: number = parameters[2].value; + let sh: BitmapHelperNew = o.intrinsicData["Actor"]; + + sh.fillAll(color, alpha); + + }, false, false, 'Füllt die ganze Bitmap mit einer Farbe. Die Farbe wird als int-Wert gegeben, wobei farbe == 255*255*rot + 255*grün + blau und 0.0 <= alpha <= 1.0', false)); + + this.addMethod(new Method("fillAll", new Parameterlist([ { identifier: "colorAsRGBAString", type: stringPrimitiveType, declaration: null, usagePositions: null, isFinal: true }, ]), voidPrimitiveType, @@ -261,8 +330,8 @@ export class BitmapHelperNew extends ShapeHelper { let uInt32 = new Uint32Array([0x11223344]); let uInt8 = new Uint8Array(uInt32.buffer); - - if(uInt8[0] === 0x44) { + + if (uInt8[0] === 0x44) { this.isBigEndian = false; } else if (uInt8[0] === 0x11) { this.isBigEndian = true; @@ -281,7 +350,7 @@ export class BitmapHelperNew extends ShapeHelper { let sprite = this.displayObject; - sprite.localTransform.scale(width/anzahlX, height/anzahlY); + sprite.localTransform.scale(width / anzahlX, height / anzahlY); sprite.localTransform.translate(left, top); //@ts-ignore sprite.transform.onChange(); @@ -301,22 +370,22 @@ export class BitmapHelperNew extends ShapeHelper { protected initGraphics(bitmapToCopy?: BitmapHelperNew, clone: boolean = false) { - if(bitmapToCopy == null){ + if (bitmapToCopy == null) { this.data = new Uint32Array(this.anzahlX * this.anzahlY); } else { - if(clone){ + if (clone) { this.data = bitmapToCopy.data; } else { this.data = new Uint32Array(bitmapToCopy.data); } } - + let u8Array = new Uint8Array(this.data.buffer); - if(!clone){ - let bufferResource = new PIXI.BufferResource(u8Array, {width: this.anzahlX, height: this.anzahlY}); + if (!clone) { + let bufferResource = new PIXI.BufferResource(u8Array, { width: this.anzahlX, height: this.anzahlY }); let bt = new PIXI.BaseTexture(bufferResource, { - scaleMode: PIXI.SCALE_MODES.NEAREST + scaleMode: PIXI.SCALE_MODES.NEAREST }); this.texture = new PIXI.Texture(bt); } else { @@ -327,7 +396,7 @@ export class BitmapHelperNew extends ShapeHelper { this.worldHelper.stage.addChild(this.displayObject); } - uploadData(){ + uploadData() { this.texture.baseTexture.update(); } @@ -358,12 +427,16 @@ export class BitmapHelperNew extends ShapeHelper { } - public istFarbe(x: number, y: number, color: string | number, alpha?: number) { + public istFarbe(x: number, y: number, color: string | number | RuntimeObject, alpha?: number) { let i = (x + y * (this.anzahlX)); let c: number; + if (color instanceof RuntimeObject) { + color = ((color.intrinsicData)).hex; + } + if (typeof color == "string") { let ch = ColorHelper.parseColorToOpenGL(color); c = ch.color; @@ -378,15 +451,19 @@ export class BitmapHelperNew extends ShapeHelper { let blue = (c1 & 0xff0000) >> 16; - return c == red*0x10000 + green * 0x100 + blue; + return c == red * 0x10000 + green * 0x100 + blue; } - public setzeFarbe(x: number, y: number, color: string | number, alpha?: number) { + public setzeFarbe(x: number, y: number, color: string | number | RuntimeObject, alpha?: number) { let i = (x + y * (this.anzahlX)); let c: number; + if (color instanceof RuntimeObject) { + color = ((color.intrinsicData)).hex; + } + if (typeof color == "string") { let ch = ColorHelper.parseColorToOpenGL(color); c = ch.color; @@ -397,13 +474,17 @@ export class BitmapHelperNew extends ShapeHelper { } this.data[i] = Math.round(alpha * 255) * 0x1000000 + ((c & 0xff) << 16) + (c & 0xff00) + ((c & 0xff0000) >> 16); - + this.uploadData(); } - public fillAll(color: string | number, alpha?: number) { + public fillAll(color: string | number | RuntimeObject, alpha?: number) { let c: number; + if (color instanceof RuntimeObject) { + color = ((color.intrinsicData)).hex; + } + if (typeof color == "string") { let ch = ColorHelper.parseColorToOpenGL(color); c = ch.color; @@ -414,12 +495,12 @@ export class BitmapHelperNew extends ShapeHelper { this.data.fill(Math.round(alpha * 255) * 0x1000000 + ((c & 0xff) << 16) + (c & 0xff00) + ((c & 0xff0000) >> 16)); // this.data.fill(0xffff0000); - + this.uploadData(); } - + public setzeFarbeRGBA(x: number, y: number, r: number, g: number, b: number, alpha: number) { - let c = alpha * 0xff000000 + b*0x10000 + g * 0x100 + r; + let c = alpha * 0xff000000 + b * 0x10000 + g * 0x100 + r; let i = (x + y * (this.anzahlX)); this.data[i] = c; this.uploadData(); diff --git a/src/client/runtimelibrary/graphics/FilledShape.ts b/src/client/runtimelibrary/graphics/FilledShape.ts index e104cd17..477e8d83 100644 --- a/src/client/runtimelibrary/graphics/FilledShape.ts +++ b/src/client/runtimelibrary/graphics/FilledShape.ts @@ -87,49 +87,64 @@ export class FilledShapeClass extends Klass { }, false, false, 'Setzt die Durchsichtigkeit von Füllung und Rand. 0.0 bedeutet vollkommen durchsichtig, 1.0 bedeutet vollkommen undurchsichtig."', false)); - this.addMethod(new Method("setFillColor", new Parameterlist([ - { identifier: "color", type: intPrimitiveType, declaration: null, usagePositions: null, isFinal: true } + this.addMethod(new Method("setDefaultBorder", new Parameterlist([ + { identifier: "width", type: doublePrimitiveType, declaration: null, usagePositions: null, isFinal: true }, + { identifier: "color", type: stringPrimitiveType, declaration: null, usagePositions: null, isFinal: true } ]), voidPrimitiveType, (parameters) => { - let o: RuntimeObject = parameters[0].value; - let color: number = parameters[1].value; - let sh: FilledShapeHelper = o.intrinsicData["Actor"]; - - if (sh.testdestroyed("setFillColor")) return; + let width: number = parameters[1].value; + let color: string = parameters[2].value; - sh.setFillColor(color); + FilledShapeDefaults.setDefaultBorder(width, color); - }, false, false, 'Setzt die Füllfarbe. Die Farbe wird als int-Wert gegeben, wobei farbe == 255*255*rot + 255*grün + blau', false)); + }, false, true, 'Setzt Default-Eigenschaften des Randes. Sie werden nachfolgend immer dann verwendet, wenn ein neues grafisches Objekt erstellt wird. Die Farbe wird als int-Wert gegeben, wobei farbe == 255*255*rot + 255*grün + blau und 0.0 <= alpha <= 1.0', false)); this.addMethod(new Method("setDefaultBorder", new Parameterlist([ { identifier: "width", type: doublePrimitiveType, declaration: null, usagePositions: null, isFinal: true }, - { identifier: "color", type: stringPrimitiveType, declaration: null, usagePositions: null, isFinal: true } + { identifier: "color", type: intPrimitiveType, declaration: null, usagePositions: null, isFinal: true }, + { identifier: "alpha", type: doublePrimitiveType, declaration: null, usagePositions: null, isFinal: true }, ]), voidPrimitiveType, (parameters) => { let width: number = parameters[1].value; - let color: string = parameters[2].value; + let color: number = parameters[2].value; + let alpha: number = parameters[3].value; - FilledShapeDefaults.setDefaultBorder(width, color); + FilledShapeDefaults.setDefaultBorder(width, color, alpha); }, false, true, 'Setzt Default-Eigenschaften des Randes. Sie werden nachfolgend immer dann verwendet, wenn ein neues grafisches Objekt erstellt wird. Die Farbe wird als int-Wert gegeben, wobei farbe == 255*255*rot + 255*grün + blau und 0.0 <= alpha <= 1.0', false)); this.addMethod(new Method("setDefaultBorder", new Parameterlist([ { identifier: "width", type: doublePrimitiveType, declaration: null, usagePositions: null, isFinal: true }, - { identifier: "color", type: intPrimitiveType, declaration: null, usagePositions: null, isFinal: true }, + { identifier: "color", type: colorType, declaration: null, usagePositions: null, isFinal: true }, { identifier: "alpha", type: doublePrimitiveType, declaration: null, usagePositions: null, isFinal: true }, ]), voidPrimitiveType, (parameters) => { let width: number = parameters[1].value; - let color: number = parameters[2].value; + let color: RuntimeObject = parameters[2].value; let alpha: number = parameters[3].value; FilledShapeDefaults.setDefaultBorder(width, color, alpha); }, false, true, 'Setzt Default-Eigenschaften des Randes. Sie werden nachfolgend immer dann verwendet, wenn ein neues grafisches Objekt erstellt wird. Die Farbe wird als int-Wert gegeben, wobei farbe == 255*255*rot + 255*grün + blau und 0.0 <= alpha <= 1.0', false)); + + this.addMethod(new Method("setDefaultBorder", new Parameterlist([ + { identifier: "width", type: doublePrimitiveType, declaration: null, usagePositions: null, isFinal: true }, + { identifier: "color", type: colorType, declaration: null, usagePositions: null, isFinal: true } + ]), voidPrimitiveType, + (parameters) => { + + let width: number = parameters[1].value; + let color: RuntimeObject = parameters[2].value; + let alpha: number = parameters[3].value; + + FilledShapeDefaults.setDefaultBorder(width, color); + + }, false, true, 'Setzt Default-Eigenschaften des Randes. Sie werden nachfolgend immer dann verwendet, wenn ein neues grafisches Objekt erstellt wird. Die Farbe wird als int-Wert gegeben, wobei farbe == 255*255*rot + 255*grün + blau und 0.0 <= alpha <= 1.0', false)); + this.addMethod(new Method("setDefaultFillColor", new Parameterlist([ { identifier: "color", type: intPrimitiveType, declaration: null, usagePositions: null, isFinal: true }, { identifier: "alpha", type: doublePrimitiveType, declaration: null, usagePositions: null, isFinal: true }, @@ -154,6 +169,46 @@ export class FilledShapeClass extends Klass { }, false, true, 'Setzt die Default-Füllfarbe. Sie wird nachfolgend immer dann verwendet, wenn ein neues grafisches Objekt erstellt wird. Die Farbe wird als int-Wert gegeben, wobei farbe == 255*255*rot + 255*grün + blau und 0.0 <= alpha <= 1.0', false)); + this.addMethod(new Method("setDefaultFillColor", new Parameterlist([ + { identifier: "color", type: colorType, declaration: null, usagePositions: null, isFinal: true }, + { identifier: "alpha", type: doublePrimitiveType, declaration: null, usagePositions: null, isFinal: true }, + ]), voidPrimitiveType, + (parameters) => { + + let color: RuntimeObject = parameters[1].value; + let alpha: number = parameters[2].value; + + FilledShapeDefaults.setDefaultFillColor(color, alpha); + + }, false, true, 'Setzt die Default-Füllfarbe. Sie wird nachfolgend immer dann verwendet, wenn ein neues grafisches Objekt erstellt wird. Die Farbe wird als int-Wert gegeben, wobei farbe == 255*255*rot + 255*grün + blau und 0.0 <= alpha <= 1.0', false)); + + this.addMethod(new Method("setDefaultFillColor", new Parameterlist([ + { identifier: "color", type: colorType, declaration: null, usagePositions: null, isFinal: true }, + ]), voidPrimitiveType, + (parameters) => { + + let color: RuntimeObject = parameters[1].value; + + FilledShapeDefaults.setDefaultFillColor(color); + + }, false, true, 'Setzt die Default-Füllfarbe. Sie wird nachfolgend immer dann verwendet, wenn ein neues grafisches Objekt erstellt wird. Die Farbe wird als int-Wert gegeben, wobei farbe == 255*255*rot + 255*grün + blau und 0.0 <= alpha <= 1.0', false)); + + this.addMethod(new Method("setFillColor", new Parameterlist([ + { identifier: "color", type: intPrimitiveType, declaration: null, usagePositions: null, isFinal: true } + ]), voidPrimitiveType, + (parameters) => { + + let o: RuntimeObject = parameters[0].value; + let color: number = parameters[1].value; + let sh: FilledShapeHelper = o.intrinsicData["Actor"]; + + if (sh.testdestroyed("setFillColor")) return; + + sh.setFillColor(color); + + }, false, false, 'Setzt die Füllfarbe. Die Farbe wird als int-Wert gegeben, wobei farbe == 255*255*rot + 255*grün + blau', false)); + + this.addMethod(new Method("setFillColor", new Parameterlist([ { identifier: "color", type: intPrimitiveType, declaration: null, usagePositions: null, isFinal: true }, { identifier: "alpha", type: doublePrimitiveType, declaration: null, usagePositions: null, isFinal: true }, @@ -203,6 +258,39 @@ export class FilledShapeClass extends Klass { }, false, false, 'Setzt die Füllfarbe. Die Farbe ist entweder eine vordefinierte Farbe (Color.black, Color.red, ...) oder eine css-Farbe der Art "#ffa7b3" oder "rgb(172, 22, 18)" und 0.0 <= alpha <= 1.0"', false)); + this.addMethod(new Method("setFillColor", new Parameterlist([ + { identifier: "color", type: colorType, declaration: null, usagePositions: null, isFinal: true }, + ]), voidPrimitiveType, + (parameters) => { + + let o: RuntimeObject = parameters[0].value; + let color: RuntimeObject = parameters[1].value; + let sh: FilledShapeHelper = o.intrinsicData["Actor"]; + + if (sh.testdestroyed("setFillColor")) return; + + sh.setFillColor(color); + + }, false, false, 'Setzt die Füllfarbe. Die Farbe ist entweder eine vordefinierte Farbe (Color.black, Color.red, ...) oder eine css-Farbe der Art "#ffa7b3" (ohne alpha), "#ffa7b380" (mit alpha), "rgb(172, 22, 18)" oder "rgba(123, 22,18, 0.3)"', false)); + + this.addMethod(new Method("setFillColor", new Parameterlist([ + { identifier: "color", type: colorType, declaration: null, usagePositions: null, isFinal: true }, + { identifier: "alpha", type: doublePrimitiveType, declaration: null, usagePositions: null, isFinal: true }, + ]), voidPrimitiveType, + (parameters) => { + + let o: RuntimeObject = parameters[0].value; + let color: RuntimeObject = parameters[1].value; + let alpha: number = parameters[2].value; + let sh: FilledShapeHelper = o.intrinsicData["Actor"]; + + if (sh.testdestroyed("setFillColor")) return; + + sh.setFillColor(color, alpha); + + }, false, false, 'Setzt die Füllfarbe. Die Farbe ist entweder eine vordefinierte Farbe (Color.black, Color.red, ...) oder eine css-Farbe der Art "#ffa7b3" oder "rgb(172, 22, 18)" und 0.0 <= alpha <= 1.0"', false)); + + this.addMethod(new Method("setBorderColor", new Parameterlist([ { identifier: "color", type: intPrimitiveType, declaration: null, usagePositions: null, isFinal: true } ]), voidPrimitiveType, @@ -267,6 +355,39 @@ export class FilledShapeClass extends Klass { }, false, false, 'Setzt die Randfarbe. Die Farbe ist entweder eine vordefinierte Farbe (Color.black, Color.red, ...) oder eine css-Farbe der Art "#ffa7b3" (ohne alpha), "#ffa7b380" (mit alpha), "rgb(172, 22, 18)" oder "rgba(123, 22,18, 0.3)"', false)); + this.addMethod(new Method("setBorderColor", new Parameterlist([ + { identifier: "color", type: colorType, declaration: null, usagePositions: null, isFinal: true }, + { identifier: "alpha", type: doublePrimitiveType, declaration: null, usagePositions: null, isFinal: true }, + ]), voidPrimitiveType, + (parameters) => { + + let o: RuntimeObject = parameters[0].value; + let color: RuntimeObject = parameters[1].value; + let alpha: number = parameters[2].value; + let sh: FilledShapeHelper = o.intrinsicData["Actor"]; + + if (sh.testdestroyed("setBorderColor")) return; + + sh.setBorderColor(color, alpha); + + }, false, false, 'Setzt die Randfarbe. Die Farbe ist entweder eine vordefinierte Farbe (Color.black, Color.red, ...) oder eine css-Farbe der Art "#ffa7b3" oder "rgb(172, 22, 18)" und 0.0 <= alpha <= 1.0"', false)); + + this.addMethod(new Method("setBorderColor", new Parameterlist([ + { identifier: "color", type: colorType, declaration: null, usagePositions: null, isFinal: true }, + ]), voidPrimitiveType, + (parameters) => { + + let o: RuntimeObject = parameters[0].value; + let color: RuntimeObject = parameters[1].value; + let sh: FilledShapeHelper = o.intrinsicData["Actor"]; + + if (sh.testdestroyed("setBorderColor")) return; + + sh.setBorderColor(color); + + }, false, false, 'Setzt die Randfarbe. Die Farbe ist entweder eine vordefinierte Farbe (Color.black, Color.red, ...) oder eine css-Farbe der Art "#ffa7b3" (ohne alpha), "#ffa7b380" (mit alpha), "rgb(172, 22, 18)" oder "rgba(123, 22,18, 0.3)"', false)); + + this.addMethod(new Method("setBorderWidth", new Parameterlist([ { identifier: "widthInPixel", type: doublePrimitiveType, declaration: null, usagePositions: null, isFinal: true }, ]), voidPrimitiveType, @@ -337,7 +458,11 @@ export abstract class FilledShapeHelper extends ShapeHelper { this.render(); } - setBorderColor(color: string | number, alpha?: number) { + setBorderColor(color: string | number | RuntimeObject, alpha?: number) { + + if (color instanceof RuntimeObject) { + color = ((color.intrinsicData)).hex; + } if (typeof color == "string") { let c = ColorHelper.parseColorToOpenGL(color); @@ -352,7 +477,11 @@ export abstract class FilledShapeHelper extends ShapeHelper { } - setFillColor(color: string | number, alpha?: number) { + setFillColor(color: string | number | RuntimeObject, alpha?: number) { + + if (color instanceof RuntimeObject) { + color = ((color.intrinsicData)).hex; + } if (typeof color == "string") { let c = ColorHelper.parseColorToOpenGL(color); diff --git a/src/client/runtimelibrary/graphics/FilledShapeDefaults.ts b/src/client/runtimelibrary/graphics/FilledShapeDefaults.ts index f49b2143..bc10cd50 100644 --- a/src/client/runtimelibrary/graphics/FilledShapeDefaults.ts +++ b/src/client/runtimelibrary/graphics/FilledShapeDefaults.ts @@ -1,3 +1,5 @@ +import { RuntimeObject } from "src/client/interpreter/RuntimeObject.js"; +import { ColorClassIntrinsicData } from "./Color.js"; import { ColorHelper } from "./ColorHelper.js"; export class FilledShapeDefaults { @@ -10,10 +12,10 @@ export class FilledShapeDefaults { static defaultVisibility: boolean = true; - static initDefaultValues(){ + static initDefaultValues() { FilledShapeDefaults.defaultFillColor = 0x8080ff; FilledShapeDefaults.defaultFillAlpha = 1.0; - + FilledShapeDefaults.defaultBorderColor = null; FilledShapeDefaults.defaultBorderAlpha = 1.0; FilledShapeDefaults.defaultBorderWidth = 10; @@ -25,10 +27,14 @@ export class FilledShapeDefaults { FilledShapeDefaults.defaultVisibility = visibility; } - static setDefaultBorder(width: number, color: string | number, alpha?: number) { + static setDefaultBorder(width: number, color: string | number | RuntimeObject, alpha?: number) { FilledShapeDefaults.defaultBorderWidth = width; + if (color instanceof RuntimeObject) { + color = ((color.intrinsicData)).hex; + } + if (typeof color == "string") { let c = ColorHelper.parseColorToOpenGL(color); FilledShapeDefaults.defaultBorderColor = c.color; @@ -40,7 +46,11 @@ export class FilledShapeDefaults { } - static setDefaultFillColor(color: string | number, alpha?: number) { + static setDefaultFillColor(color: string | number | RuntimeObject, alpha?: number) { + + if (color instanceof RuntimeObject) { + color = ((color.intrinsicData)).hex; + } if (typeof color == "string") { let c = ColorHelper.parseColorToOpenGL(color); diff --git a/src/client/runtimelibrary/graphics/Shape.ts b/src/client/runtimelibrary/graphics/Shape.ts index b95bce15..9051fd91 100644 --- a/src/client/runtimelibrary/graphics/Shape.ts +++ b/src/client/runtimelibrary/graphics/Shape.ts @@ -14,6 +14,7 @@ import { CircleHelper } from "./Circle.js"; import { TurtleHelper } from "./Turtle.js"; import { Enum, EnumInfo } from "../../compiler/types/Enum.js"; import { FilledShapeDefaults } from "./FilledShapeDefaults.js"; +import { ColorClassIntrinsicData } from "./Color.js"; export class ShapeClass extends Klass { @@ -28,6 +29,7 @@ export class ShapeClass extends Klass { let shapeType = module.typeStore.getType("Shape"); let directionType = (module.typeStore.getType("Direction")); let shapeArrayType = new ArrayType(shapeType); + let colorType: Klass = this.module.typeStore.getType("Color"); let vector2Class = module.typeStore.getType("Vector2"); @@ -550,6 +552,22 @@ export class ShapeClass extends Klass { }, false, false, 'Überzieht das Grafikobjekt mit einer halbdurchsichtigen Farbschicht. Die Farbe wird als int-Wert angegeben, praktischerweise hexadezimal, also z.B. tint(0x303030).', false)); + this.addMethod(new Method("tint", new Parameterlist([ + { identifier: "color", type: colorType, declaration: null, usagePositions: null, isFinal: true }, + ]), voidPrimitiveType, + (parameters) => { + + let o: RuntimeObject = parameters[0].value; + let color: RuntimeObject = parameters[1].value; + let sh: ShapeHelper = o.intrinsicData["Actor"]; + + if (sh.testdestroyed("tint")) return; + + sh.tint(color); + + }, false, false, 'Überzieht das Grafikobjekt mit einer halbdurchsichtigen Farbschicht. Die Farbe wird als int-Wert angegeben, praktischerweise hexadezimal, also z.B. tint(0x303030).', false)); + + this.addMethod(new Method("startTrackingEveryMouseMovement", new Parameterlist([ ]), voidPrimitiveType, (parameters) => { @@ -829,8 +847,11 @@ export abstract class ShapeHelper extends ActorHelper { } } - tint(color: string | number) { + tint(color: string | number | RuntimeObject) { let c: number; + if (color instanceof RuntimeObject) { + color = ((color.intrinsicData)).hex; + } if (typeof color == 'string') { c = ColorHelper.parseColorToOpenGL(color).color; } else { diff --git a/src/client/runtimelibrary/graphics/World.ts b/src/client/runtimelibrary/graphics/World.ts index 4e4e3b5a..e406b0ed 100644 --- a/src/client/runtimelibrary/graphics/World.ts +++ b/src/client/runtimelibrary/graphics/World.ts @@ -5,6 +5,7 @@ import { Method, Parameterlist, Value } from "../../compiler/types/Types.js"; import { Interpreter, InterpreterState } from "../../interpreter/Interpreter.js"; import { RuntimeObject } from "../../interpreter/RuntimeObject.js"; import { ActorHelper } from "./Actor.js"; +import { ColorClassIntrinsicData } from "./Color.js"; import { ColorHelper } from "./ColorHelper.js"; import { FilledShapeDefaults } from "./FilledShapeDefaults.js"; import { GroupClass, GroupHelper } from "./Group.js"; @@ -23,6 +24,7 @@ export class WorldClass extends Klass { let groupType = module.typeStore.getType("Group"); let shapeType = module.typeStore.getType("Shape"); let mouseListenerType = module.typeStore.getType("MouseListener"); + let colorType: Klass = this.module.typeStore.getType("Color"); // this.addAttribute(new Attribute("PI", doublePrimitiveType, (object) => { return Math.PI }, true, Visibility.public, true, "Die Kreiszahl Pi (3.1415...)")); @@ -76,6 +78,20 @@ export class WorldClass extends Klass { }, false, false, 'Setzt die Hintergrundfarbe. Die Farbe ist entweder eine vordefinierte Farbe ("schwarz", "rot", ...) oder eine css-Farbe der Art "#ffa7b3" (ohne alpha), "#ffa7b380" (mit alpha), "rgb(172, 22, 18)" oder "rgba(123, 22,18, 0.3)"', false)); + this.addMethod(new Method("setBackgroundColor", new Parameterlist([ + { identifier: "color", type: colorType, declaration: null, usagePositions: null, isFinal: true }, + ]), voidPrimitiveType, + (parameters) => { + + let o: RuntimeObject = parameters[0].value; + let color: RuntimeObject = parameters[1].value; + let wh: WorldHelper = o.intrinsicData["World"]; + + wh.setBackgroundColor(color); + + }, false, false, 'Setzt die Hintergrundfarbe. Die Farbe ist entweder eine vordefinierte Farbe ("schwarz", "rot", ...) oder eine css-Farbe der Art "#ffa7b3" (ohne alpha), "#ffa7b380" (mit alpha), "rgb(172, 22, 18)" oder "rgba(123, 22,18, 0.3)"', false)); + + this.addMethod(new Method("move", new Parameterlist([ { identifier: "x", type: doublePrimitiveType, declaration: null, usagePositions: null, isFinal: true }, { identifier: "y", type: doublePrimitiveType, declaration: null, usagePositions: null, isFinal: true }, @@ -797,7 +813,11 @@ export class WorldHelper { } - setBackgroundColor(color: string | number) { + setBackgroundColor(color: string | number | RuntimeObject) { + + if (color instanceof RuntimeObject) { + color = ((color.intrinsicData)).hex; + } if (typeof color == "string") { let c = ColorHelper.parseColorToOpenGL(color); From 045cde4d4e562bbb1b79d02892930a13dca682d5 Mon Sep 17 00:00:00 2001 From: InformaTiger Date: Fri, 1 Jul 2022 22:30:51 +0200 Subject: [PATCH 07/12] fixed import error --- src/client/runtimelibrary/graphics/FilledShapeDefaults.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/runtimelibrary/graphics/FilledShapeDefaults.ts b/src/client/runtimelibrary/graphics/FilledShapeDefaults.ts index bc10cd50..b8fcb364 100644 --- a/src/client/runtimelibrary/graphics/FilledShapeDefaults.ts +++ b/src/client/runtimelibrary/graphics/FilledShapeDefaults.ts @@ -1,4 +1,4 @@ -import { RuntimeObject } from "src/client/interpreter/RuntimeObject.js"; +import { RuntimeObject } from "../../interpreter/RuntimeObject.js"; import { ColorClassIntrinsicData } from "./Color.js"; import { ColorHelper } from "./ColorHelper.js"; From ea4b168b179840f44bcbd00be00923fa1f3950e2 Mon Sep 17 00:00:00 2001 From: InformaTiger Date: Sat, 2 Jul 2022 12:53:57 +0200 Subject: [PATCH 08/12] added `.0` in static `toString()`-methods of `Double` and `Float` --- src/client/compiler/types/boxedTypes/DoubleClass.ts | 2 +- src/client/compiler/types/boxedTypes/FloatClass.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/compiler/types/boxedTypes/DoubleClass.ts b/src/client/compiler/types/boxedTypes/DoubleClass.ts index 3b350d3a..3e7376cc 100644 --- a/src/client/compiler/types/boxedTypes/DoubleClass.ts +++ b/src/client/compiler/types/boxedTypes/DoubleClass.ts @@ -106,7 +106,7 @@ export class DoubleClass extends UnboxableKlass { { identifier: "f", type: doublePrimitiveType, declaration: null, usagePositions: null, isFinal: true } ]), stringPrimitiveType, (parameters) => { - return "" + parameters[1].value; + return floatToString(parameters[1].value); }, false, true, "Gibt die übergebene Zahl als String-Wert zurück.")); this.addMethod(new Method("valueOf", new Parameterlist([ diff --git a/src/client/compiler/types/boxedTypes/FloatClass.ts b/src/client/compiler/types/boxedTypes/FloatClass.ts index 02868eb3..09e119f5 100644 --- a/src/client/compiler/types/boxedTypes/FloatClass.ts +++ b/src/client/compiler/types/boxedTypes/FloatClass.ts @@ -106,7 +106,7 @@ export class FloatClass extends UnboxableKlass { { identifier: "f", type: floatPrimitiveType, declaration: null, usagePositions: null, isFinal: true } ]), stringPrimitiveType, (parameters) => { - return "" + parameters[1].value; + return floatToString(parameters[1].value); }, false, true, "Gibt die übergebene Zahl als String-Wert zurück.")); this.addMethod(new Method("valueOf", new Parameterlist([ From 97c862b21919abb28d2c57b6923b529cd3b8d7ec Mon Sep 17 00:00:00 2001 From: InformaTiger Date: Sat, 2 Jul 2022 14:26:30 +0200 Subject: [PATCH 09/12] removed unnescessary lines --- src/client/compiler/types/PrimitiveTypes.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/client/compiler/types/PrimitiveTypes.ts b/src/client/compiler/types/PrimitiveTypes.ts index 70ac23e5..db351a00 100644 --- a/src/client/compiler/types/PrimitiveTypes.ts +++ b/src/client/compiler/types/PrimitiveTypes.ts @@ -686,9 +686,7 @@ export class StringPrimitiveType extends Klass { init() { this.operationTable = { [TokenType.plus]: { - "String": stringPrimitiveType //, "int": stringPrimitiveType, - // "float": stringPrimitiveType, "double": stringPrimitiveType, - // "boolean": stringPrimitiveType, "char": stringPrimitiveType + "String": stringPrimitiveType }, [TokenType.equal]: { "String": booleanPrimitiveType, "null": booleanPrimitiveType }, [TokenType.notEqual]: { "String": booleanPrimitiveType, "null": booleanPrimitiveType }, @@ -805,12 +803,8 @@ export class StringPrimitiveType extends Klass { switch (operation) { case TokenType.plus: - if (secondOperand.type == stringPrimitiveType || secondOperand.type == charPrimitiveType) { + if (secondOperand.type == stringPrimitiveType) { return nullToString(value) + (secondOperand.value); // because null + null = 0 in javascript - } else if (secondOperand.type == booleanPrimitiveType) { - return nullToString(value) + (secondOperand.value); - } else { - return nullToString(value) + (secondOperand.value); } case TokenType.lower: From 0fbeaf284adeeaee253d1ee3f6c65a66718b4fa0 Mon Sep 17 00:00:00 2001 From: InformaTiger Date: Sat, 2 Jul 2022 15:55:31 +0200 Subject: [PATCH 10/12] simplified casting --- src/client/compiler/parser/CodeGenerator.ts | 69 ++++++------------- src/client/compiler/types/Class.ts | 9 ++- .../compiler/types/boxedTypes/BooleanClass.ts | 4 -- .../types/boxedTypes/CharacterClass.ts | 4 -- .../compiler/types/boxedTypes/DoubleClass.ts | 4 -- .../compiler/types/boxedTypes/FloatClass.ts | 4 -- .../compiler/types/boxedTypes/IntegerClass.ts | 4 -- .../compiler/types/boxedTypes/LongClass.ts | 4 -- 8 files changed, 29 insertions(+), 73 deletions(-) diff --git a/src/client/compiler/parser/CodeGenerator.ts b/src/client/compiler/parser/CodeGenerator.ts index 714c5b3b..6b0c2a78 100644 --- a/src/client/compiler/parser/CodeGenerator.ts +++ b/src/client/compiler/parser/CodeGenerator.ts @@ -817,61 +817,45 @@ export class CodeGenerator { } - ensureAutomaticCasting(typeFrom: Type, typeTo: Type, position?: TextPosition, nodeFrom?: ASTNode, nullTypeForbidden: boolean = false): boolean { + ensureAutomaticCasting(typeFrom: Type, typeTo: Type, position?: TextPosition, nodeFrom?: ASTNode): boolean { if (typeFrom == null || typeTo == null) return false; - if (!(typeFrom == nullType && nullTypeForbidden)) { + if (typeFrom.equals(typeTo)) { + return true; + } - if (typeFrom.equals(typeTo)) { - return true; + if (typeFrom.canCastTo(typeTo)) { + if (typeFrom instanceof PrimitiveType && (typeTo instanceof PrimitiveType || typeTo == stringPrimitiveType)) { + let castInfo = typeFrom.getCastInformation(typeTo); + if (!castInfo.automatic) { + return false; + } } + this.pushStatements({ + type: TokenType.castValue, + position: position, + newType: typeTo + }); + return true; + } + else { if (!typeFrom.canCastTo(typeTo)) { - if (typeTo == booleanPrimitiveType && nodeFrom != null) { - this.checkIfAssignmentInstedOfEqual(nodeFrom); - } - - - return false; } - - if (typeFrom["unboxableAs"] != null && typeFrom["unboxableAs"].indexOf(typeTo) >= 0) { - this.pushStatements({ - type: TokenType.castValue, - position: position, - newType: typeTo - }); - return true; - } - - } - - - if (typeFrom instanceof PrimitiveType && (typeTo instanceof PrimitiveType || typeTo == stringPrimitiveType)) { - let castInfo = typeFrom.getCastInformation(typeTo); - if (!castInfo.automatic) { - return false; - } - this.pushStatements({ - type: TokenType.castValue, - newType: typeTo, - position: position - }); + return false; } - return true; - } ensureAutomaticToString(typeFrom: Type, codepos: number = undefined, textposition?: TextPosition): boolean { if (typeFrom == stringPrimitiveType) return true; if (typeFrom == voidPrimitiveType) return false; let automaticToString: Method; - + if (typeFrom instanceof PrimitiveType) { automaticToString = new Method("toString", new Parameterlist([]), stringPrimitiveType, (parameters: Value[]) => { let value = parameters[0]; @@ -1333,15 +1317,6 @@ export class CodeGenerator { } - if (typeFrom instanceof UnboxableKlass) { - for (let unboxableAs of typeFrom.unboxableAs) { - if (unboxableAs.canCastTo(typeTo)) { - this.pushCastToStatement(typeFrom, unboxableAs, node); - this.pushCastToStatement(unboxableAs, typeTo, node); - } - } - } - if ((typeFrom instanceof Klass || typeFrom instanceof Interface) && (typeTo instanceof Klass || typeTo instanceof Interface)) // if (typeFrom instanceof Klass && @@ -3177,7 +3152,7 @@ export class CodeGenerator { let convertedLeftType = leftType.type; if (isAssignment) { - if (!this.ensureAutomaticCasting(rightType.type, leftType.type, node.position, node.firstOperand, true)) { + if (!this.ensureAutomaticCasting(rightType.type, leftType.type, node.position, node.firstOperand)) { this.pushError("Der Wert vom Datentyp " + rightType.type.identifier + " auf der rechten Seite kann der Variablen auf der linken Seite (Datentyp " + leftType.type.identifier + ") nicht zugewiesen werden.", node.position); return leftType; } @@ -3312,7 +3287,7 @@ export class CodeGenerator { if (leftType == null) return; - if (this.ensureAutomaticCasting(leftType.type, booleanPrimitiveType, null, node.firstOperand, true)) { + if (this.ensureAutomaticCasting(leftType.type, booleanPrimitiveType, null, node.firstOperand)) { let secondOperand = node.secondOperand; if (secondOperand != null) { diff --git a/src/client/compiler/types/Class.ts b/src/client/compiler/types/Class.ts index 79cd79eb..ebb128c7 100644 --- a/src/client/compiler/types/Class.ts +++ b/src/client/compiler/types/Class.ts @@ -1493,9 +1493,9 @@ export class UnboxableKlass extends Klass { public unboxableAs: Type[] = []; public castTo(value: Value, type: Type): Value { - if (! (type instanceof PrimitiveType)) return null; + if (!(type instanceof PrimitiveType)) return null; if (this.unboxableAs.includes(type)) { - if (value.value == null && ! type.allowsNull()) throw Error("null kann nicht in einen primitiven " + type.identifier + " umgewandelt werden."); + if (value.value == null && !type.allowsNull()) throw Error("null kann nicht in einen primitiven " + type.identifier + " umgewandelt werden."); else return { value: value.value, type: type @@ -1503,4 +1503,9 @@ export class UnboxableKlass extends Klass { } return null; } + + canCastTo(type: Type): boolean { + return this.unboxableAs.indexOf(type) >= 0 || super.canCastTo(type); + } + } \ No newline at end of file diff --git a/src/client/compiler/types/boxedTypes/BooleanClass.ts b/src/client/compiler/types/boxedTypes/BooleanClass.ts index 94d677a5..78b52dbe 100644 --- a/src/client/compiler/types/boxedTypes/BooleanClass.ts +++ b/src/client/compiler/types/boxedTypes/BooleanClass.ts @@ -18,10 +18,6 @@ export class BooleanClass extends UnboxableKlass { } - canCastTo(type: Type): boolean { - return this.unboxableAs.indexOf(type) >= 0 || super.canCastTo(type); - } - init() { this.unboxableAs = [booleanPrimitiveType]; diff --git a/src/client/compiler/types/boxedTypes/CharacterClass.ts b/src/client/compiler/types/boxedTypes/CharacterClass.ts index 061c241b..c3e66db0 100644 --- a/src/client/compiler/types/boxedTypes/CharacterClass.ts +++ b/src/client/compiler/types/boxedTypes/CharacterClass.ts @@ -15,10 +15,6 @@ export class CharacterClass extends UnboxableKlass { } - canCastTo(type: Type): boolean { - return this.unboxableAs.indexOf(type) >= 0 || super.canCastTo(type); - } - init() { this.unboxableAs = [charPrimitiveType, stringPrimitiveType]; diff --git a/src/client/compiler/types/boxedTypes/DoubleClass.ts b/src/client/compiler/types/boxedTypes/DoubleClass.ts index 3e7376cc..d366655b 100644 --- a/src/client/compiler/types/boxedTypes/DoubleClass.ts +++ b/src/client/compiler/types/boxedTypes/DoubleClass.ts @@ -22,10 +22,6 @@ export class DoubleClass extends UnboxableKlass { } - canCastTo(type: Type): boolean { - return this.unboxableAs.indexOf(type) >= 0 || super.canCastTo(type); - } - init() { this.unboxableAs = [doublePrimitiveType]; diff --git a/src/client/compiler/types/boxedTypes/FloatClass.ts b/src/client/compiler/types/boxedTypes/FloatClass.ts index 09e119f5..f62dc60f 100644 --- a/src/client/compiler/types/boxedTypes/FloatClass.ts +++ b/src/client/compiler/types/boxedTypes/FloatClass.ts @@ -22,10 +22,6 @@ export class FloatClass extends UnboxableKlass { } - canCastTo(type: Type): boolean { - return this.unboxableAs.indexOf(type) >= 0 || super.canCastTo(type); - } - init() { this.unboxableAs = [floatPrimitiveType, doublePrimitiveType]; diff --git a/src/client/compiler/types/boxedTypes/IntegerClass.ts b/src/client/compiler/types/boxedTypes/IntegerClass.ts index 98c3de06..642ee3ab 100644 --- a/src/client/compiler/types/boxedTypes/IntegerClass.ts +++ b/src/client/compiler/types/boxedTypes/IntegerClass.ts @@ -19,10 +19,6 @@ export class IntegerClass extends UnboxableKlass { } - canCastTo(type: Type): boolean{ - return this.unboxableAs.indexOf(type) >= 0 || super.canCastTo(type); - } - init() { this.unboxableAs = [intPrimitiveType, floatPrimitiveType, doublePrimitiveType]; diff --git a/src/client/compiler/types/boxedTypes/LongClass.ts b/src/client/compiler/types/boxedTypes/LongClass.ts index 8c5100af..bfa449b5 100644 --- a/src/client/compiler/types/boxedTypes/LongClass.ts +++ b/src/client/compiler/types/boxedTypes/LongClass.ts @@ -19,10 +19,6 @@ export class LongClass extends UnboxableKlass { } - canCastTo(type: Type): boolean{ - return this.unboxableAs.indexOf(type) >= 0 || super.canCastTo(type); - } - init() { this.unboxableAs = [intPrimitiveType, longPrimitiveType, floatPrimitiveType, doublePrimitiveType]; From dc08466ce06412f6d29c8c617ed594af3fd012a7 Mon Sep 17 00:00:00 2001 From: InformaTiger Date: Sat, 2 Jul 2022 16:11:03 +0200 Subject: [PATCH 11/12] Integer unboxableAs long --- src/client/compiler/types/boxedTypes/IntegerClass.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/compiler/types/boxedTypes/IntegerClass.ts b/src/client/compiler/types/boxedTypes/IntegerClass.ts index 642ee3ab..fa6d63dd 100644 --- a/src/client/compiler/types/boxedTypes/IntegerClass.ts +++ b/src/client/compiler/types/boxedTypes/IntegerClass.ts @@ -1,6 +1,6 @@ import { Klass, UnboxableKlass, Visibility } from "../Class.js"; import { Method, Parameterlist, Attribute, Value, Type, PrimitiveType } from "../Types.js"; -import { intPrimitiveType, stringPrimitiveType, doublePrimitiveType, floatPrimitiveType, booleanPrimitiveType } from "../PrimitiveTypes.js"; +import { intPrimitiveType, stringPrimitiveType, doublePrimitiveType, floatPrimitiveType, booleanPrimitiveType, longPrimitiveType } from "../PrimitiveTypes.js"; import { RuntimeObject } from "../../../interpreter/RuntimeObject.js"; @@ -21,7 +21,7 @@ export class IntegerClass extends UnboxableKlass { init() { - this.unboxableAs = [intPrimitiveType, floatPrimitiveType, doublePrimitiveType]; + this.unboxableAs = [intPrimitiveType, floatPrimitiveType, doublePrimitiveType, longPrimitiveType]; this.addMethod(new Method("Integer", new Parameterlist([ { identifier: "int-wert", type: intPrimitiveType, declaration: null, usagePositions: null, isFinal: true } From ed88f6e7d335a2b085c0ed1c410e1b60d9fc0190 Mon Sep 17 00:00:00 2001 From: InformaTiger Date: Sat, 2 Jul 2022 16:20:58 +0200 Subject: [PATCH 12/12] int can be casted to Long --- src/client/compiler/types/PrimitiveTypes.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/client/compiler/types/PrimitiveTypes.ts b/src/client/compiler/types/PrimitiveTypes.ts index db351a00..958fdf40 100644 --- a/src/client/compiler/types/PrimitiveTypes.ts +++ b/src/client/compiler/types/PrimitiveTypes.ts @@ -118,6 +118,7 @@ export class IntPrimitiveType extends PrimitiveType { "int": { automatic: true, needsStatement: false }, "long": { automatic: true, needsStatement: false }, "Integer": { automatic: true, needsStatement: true }, + "Long": { automatic: true, needsStatement: true }, }