From 629db573859f745690d9b965f75be8d542c2212c Mon Sep 17 00:00:00 2001 From: raylras Date: Sat, 23 Nov 2024 16:43:13 +0800 Subject: [PATCH 01/11] prepare operator overloading --- packages/zenscript/src/builtins/bool.dzs | 4 +++- packages/zenscript/src/builtins/byte.dzs | 4 +++- packages/zenscript/src/builtins/double.dzs | 4 +++- packages/zenscript/src/builtins/float.dzs | 4 +++- packages/zenscript/src/builtins/int.dzs | 4 +++- packages/zenscript/src/builtins/long.dzs | 4 +++- packages/zenscript/src/builtins/short.dzs | 4 +++- packages/zenscript/src/builtins/string.dzs | 2 ++ .../zenscript/src/typing/type-computer.ts | 19 +++++++++---------- 9 files changed, 32 insertions(+), 17 deletions(-) diff --git a/packages/zenscript/src/builtins/bool.dzs b/packages/zenscript/src/builtins/bool.dzs index 1df8d3f5..155ece65 100644 --- a/packages/zenscript/src/builtins/bool.dzs +++ b/packages/zenscript/src/builtins/bool.dzs @@ -1 +1,3 @@ -zenClass bool +zenClass bool { + operator as() as string +} diff --git a/packages/zenscript/src/builtins/byte.dzs b/packages/zenscript/src/builtins/byte.dzs index b88cbffc..97f515ac 100644 --- a/packages/zenscript/src/builtins/byte.dzs +++ b/packages/zenscript/src/builtins/byte.dzs @@ -1 +1,3 @@ -zenClass byte +zenClass byte { + operator as() as short, int, long, float, double, string +} diff --git a/packages/zenscript/src/builtins/double.dzs b/packages/zenscript/src/builtins/double.dzs index 39ec4f23..8396e6d6 100644 --- a/packages/zenscript/src/builtins/double.dzs +++ b/packages/zenscript/src/builtins/double.dzs @@ -1 +1,3 @@ -zenClass double +zenClass double { + operator as() as byte, short, int, long, float, string +} diff --git a/packages/zenscript/src/builtins/float.dzs b/packages/zenscript/src/builtins/float.dzs index 873011b0..9b1e0eaf 100644 --- a/packages/zenscript/src/builtins/float.dzs +++ b/packages/zenscript/src/builtins/float.dzs @@ -1 +1,3 @@ -zenClass float +zenClass float { + operator as() as byte, short, int, long, double, string +} diff --git a/packages/zenscript/src/builtins/int.dzs b/packages/zenscript/src/builtins/int.dzs index 700903b9..9099b306 100644 --- a/packages/zenscript/src/builtins/int.dzs +++ b/packages/zenscript/src/builtins/int.dzs @@ -1 +1,3 @@ -zenClass int +zenClass int { + operator as() as byte, short, long, float, double, string +} diff --git a/packages/zenscript/src/builtins/long.dzs b/packages/zenscript/src/builtins/long.dzs index 00c175ff..599202e9 100644 --- a/packages/zenscript/src/builtins/long.dzs +++ b/packages/zenscript/src/builtins/long.dzs @@ -1 +1,3 @@ -zenClass long +zenClass long { + operator as() as byte, short, int, float, double, string +} diff --git a/packages/zenscript/src/builtins/short.dzs b/packages/zenscript/src/builtins/short.dzs index de4b3b14..3d41b892 100644 --- a/packages/zenscript/src/builtins/short.dzs +++ b/packages/zenscript/src/builtins/short.dzs @@ -1 +1,3 @@ -zenClass short +zenClass short { + operator as() as byte, int, long, float, double, string +} diff --git a/packages/zenscript/src/builtins/string.dzs b/packages/zenscript/src/builtins/string.dzs index 99675566..42c6ade3 100644 --- a/packages/zenscript/src/builtins/string.dzs +++ b/packages/zenscript/src/builtins/string.dzs @@ -84,4 +84,6 @@ zenClass string { function lastIndexOf(needle as string, fromIndex as int) as int; function split(separator as string, maximum as int = 0) as [string]; + + operator as() as bool, byte, int, short, long, float, double } diff --git a/packages/zenscript/src/typing/type-computer.ts b/packages/zenscript/src/typing/type-computer.ts index e3bdb479..5e7de264 100644 --- a/packages/zenscript/src/typing/type-computer.ts +++ b/packages/zenscript/src/typing/type-computer.ts @@ -207,9 +207,8 @@ export class ZenScriptTypeComputer implements TypeComputer { return this.inferType(source.right) }, - ConditionalExpression: (_) => { - // TODO: operator overloading - return this.classTypeOf('bool') + ConditionalExpression: (source) => { + return this.inferType(source.second) ?? this.inferType(source.third) }, PrefixExpression: (source) => { @@ -260,7 +259,7 @@ export class ZenScriptTypeComputer implements TypeComputer { return this.inferType(source.typeRef) }, - InstanceofExpression: (_) => { + InstanceofExpression: () => { return this.classTypeOf('bool') }, @@ -347,12 +346,12 @@ export class ZenScriptTypeComputer implements TypeComputer { } }, - NullLiteral: (_) => { - // TODO: does it make sense? + NullLiteral: () => { + // does it make sense? return this.classTypeOf('any') }, - BooleanLiteral: (_) => { + BooleanLiteral: () => { return this.classTypeOf('bool') }, @@ -382,15 +381,15 @@ export class ZenScriptTypeComputer implements TypeComputer { } }, - StringLiteral: (_) => { + StringLiteral: () => { return this.classTypeOf('string') }, - UnquotedString: (_) => { + UnquotedString: () => { return this.classTypeOf('string') }, - StringTemplate: (_) => { + StringTemplate: () => { return this.classTypeOf('string') }, From 6d75528e8d20ed31367fa07bcd0342d8a428ec83 Mon Sep 17 00:00:00 2001 From: raylras Date: Sat, 23 Nov 2024 17:36:17 +0800 Subject: [PATCH 02/11] more operators --- packages/zenscript/src/builtins/byte.dzs | 3 ++- packages/zenscript/src/builtins/double.dzs | 3 ++- packages/zenscript/src/builtins/float.dzs | 3 ++- packages/zenscript/src/builtins/int.dzs | 3 ++- packages/zenscript/src/builtins/long.dzs | 3 ++- packages/zenscript/src/builtins/short.dzs | 3 ++- packages/zenscript/src/builtins/string.dzs | 4 +++- 7 files changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/zenscript/src/builtins/byte.dzs b/packages/zenscript/src/builtins/byte.dzs index 97f515ac..0855c5be 100644 --- a/packages/zenscript/src/builtins/byte.dzs +++ b/packages/zenscript/src/builtins/byte.dzs @@ -1,3 +1,4 @@ zenClass byte { - operator as() as short, int, long, float, double, string + operator -() as byte; + operator as() as short, int, long, float, double, string; } diff --git a/packages/zenscript/src/builtins/double.dzs b/packages/zenscript/src/builtins/double.dzs index 8396e6d6..d43bfcb6 100644 --- a/packages/zenscript/src/builtins/double.dzs +++ b/packages/zenscript/src/builtins/double.dzs @@ -1,3 +1,4 @@ zenClass double { - operator as() as byte, short, int, long, float, string + operator -() as double; + operator as() as byte, short, int, long, float, string; } diff --git a/packages/zenscript/src/builtins/float.dzs b/packages/zenscript/src/builtins/float.dzs index 9b1e0eaf..9180895e 100644 --- a/packages/zenscript/src/builtins/float.dzs +++ b/packages/zenscript/src/builtins/float.dzs @@ -1,3 +1,4 @@ zenClass float { - operator as() as byte, short, int, long, double, string + operator -() as float; + operator as() as byte, short, int, long, double, string; } diff --git a/packages/zenscript/src/builtins/int.dzs b/packages/zenscript/src/builtins/int.dzs index 9099b306..5a628648 100644 --- a/packages/zenscript/src/builtins/int.dzs +++ b/packages/zenscript/src/builtins/int.dzs @@ -1,3 +1,4 @@ zenClass int { - operator as() as byte, short, long, float, double, string + operator -() as int; + operator as() as byte, short, long, float, double, string; } diff --git a/packages/zenscript/src/builtins/long.dzs b/packages/zenscript/src/builtins/long.dzs index 599202e9..712d3c4b 100644 --- a/packages/zenscript/src/builtins/long.dzs +++ b/packages/zenscript/src/builtins/long.dzs @@ -1,3 +1,4 @@ zenClass long { - operator as() as byte, short, int, float, double, string + operator -() as long; + operator as() as byte, short, int, float, double, string; } diff --git a/packages/zenscript/src/builtins/short.dzs b/packages/zenscript/src/builtins/short.dzs index 3d41b892..40d51158 100644 --- a/packages/zenscript/src/builtins/short.dzs +++ b/packages/zenscript/src/builtins/short.dzs @@ -1,3 +1,4 @@ zenClass short { - operator as() as byte, int, long, float, double, string + operator -() as short; + operator as() as byte, int, long, float, double, string; } diff --git a/packages/zenscript/src/builtins/string.dzs b/packages/zenscript/src/builtins/string.dzs index 42c6ade3..9153871d 100644 --- a/packages/zenscript/src/builtins/string.dzs +++ b/packages/zenscript/src/builtins/string.dzs @@ -85,5 +85,7 @@ zenClass string { function split(separator as string, maximum as int = 0) as [string]; - operator as() as bool, byte, int, short, long, float, double + operator +(value as string) as string; + + operator as() as bool, byte, int, short, long, float, double; } From 255d6d01315509aa207d67404870dc379abc42a1 Mon Sep 17 00:00:00 2001 From: raylras Date: Sat, 23 Nov 2024 17:47:27 +0800 Subject: [PATCH 03/11] impl unary `-` --- packages/zenscript/src/typing/type-computer.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/zenscript/src/typing/type-computer.ts b/packages/zenscript/src/typing/type-computer.ts index 5e7de264..1aaa6736 100644 --- a/packages/zenscript/src/typing/type-computer.ts +++ b/packages/zenscript/src/typing/type-computer.ts @@ -213,8 +213,16 @@ export class ZenScriptTypeComputer implements TypeComputer { PrefixExpression: (source) => { switch (source.op) { - case '-': - return this.classTypeOf('int') + case '-': { + const operatorDecl = stream(this.memberProvider().getMembers(source.expr)) + .map(it => it.node) + .filter(isOperatorFunctionDeclaration) + .filter(it => it.op === '-') + .filter(it => it.parameters.length === 0) + .head() + return this.inferType(operatorDecl?.returnTypeRef) + } + case '!': return this.classTypeOf('bool') } From 357d1492fdb0f53965cd8a573db0041d6e168d8e Mon Sep 17 00:00:00 2001 From: raylras Date: Mon, 25 Nov 2024 15:36:44 +0800 Subject: [PATCH 04/11] sync main --- packages/zenscript/src/typing/type-computer.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/zenscript/src/typing/type-computer.ts b/packages/zenscript/src/typing/type-computer.ts index b08a3a1f..10b9e87d 100644 --- a/packages/zenscript/src/typing/type-computer.ts +++ b/packages/zenscript/src/typing/type-computer.ts @@ -212,8 +212,7 @@ export class ZenScriptTypeComputer implements TypeComputer { PrefixExpression: (source) => { switch (source.op) { case '-': { - const operatorDecl = stream(this.memberProvider().getMembers(source.expr)) - .map(it => it.node) + const operatorDecl = this.memberProvider().streamMembers(source.expr) .filter(isOperatorFunctionDeclaration) .filter(it => it.op === '-') .filter(it => it.parameters.length === 0) From 0504c91b55fbe0a73ec1b24afc8b6a95d2de7307 Mon Sep 17 00:00:00 2001 From: raylras Date: Mon, 25 Nov 2024 18:38:45 +0800 Subject: [PATCH 05/11] impl more operators --- packages/zenscript/src/builtins/bool.dzs | 9 ++ packages/zenscript/src/builtins/byte.dzs | 19 +++++ packages/zenscript/src/builtins/double.dzs | 18 ++++ packages/zenscript/src/builtins/float.dzs | 14 ++++ packages/zenscript/src/builtins/int.dzs | 23 +++++ packages/zenscript/src/builtins/long.dzs | 19 +++++ packages/zenscript/src/builtins/short.dzs | 19 +++++ packages/zenscript/src/builtins/string.dzs | 4 + .../src/reference/member-provider.ts | 11 ++- .../zenscript/src/typing/type-computer.ts | 83 ++++++++++++------- 10 files changed, 184 insertions(+), 35 deletions(-) diff --git a/packages/zenscript/src/builtins/bool.dzs b/packages/zenscript/src/builtins/bool.dzs index 155ece65..01b2f4f7 100644 --- a/packages/zenscript/src/builtins/bool.dzs +++ b/packages/zenscript/src/builtins/bool.dzs @@ -1,3 +1,12 @@ zenClass bool { + operator !() as bool; + + operator &(value as bool) as bool; + operator |(value as bool) as bool; + operator ^(value as bool) as bool; + + operator ==(value as bool) as bool; + operator !=(value as bool) as bool; + operator as() as string } diff --git a/packages/zenscript/src/builtins/byte.dzs b/packages/zenscript/src/builtins/byte.dzs index 0855c5be..1a98933e 100644 --- a/packages/zenscript/src/builtins/byte.dzs +++ b/packages/zenscript/src/builtins/byte.dzs @@ -1,4 +1,23 @@ zenClass byte { operator -() as byte; + operator !() as byte; + + operator &(value as byte) as byte; + operator |(value as byte) as byte; + operator ^(value as byte) as byte; + + operator +(value as byte) as byte; + operator -(value as byte) as byte; + operator *(value as byte) as byte; + operator /(value as byte) as byte; + operator %(value as byte) as byte; + + operator <(value as byte) as bool; + operator >(value as byte) as bool; + operator <=(value as byte) as bool; + operator >=(value as byte) as bool; + operator ==(value as byte) as bool; + operator !=(value as byte) as bool; + operator as() as short, int, long, float, double, string; } diff --git a/packages/zenscript/src/builtins/double.dzs b/packages/zenscript/src/builtins/double.dzs index d43bfcb6..5542419c 100644 --- a/packages/zenscript/src/builtins/double.dzs +++ b/packages/zenscript/src/builtins/double.dzs @@ -1,4 +1,22 @@ zenClass double { operator -() as double; + + operator &(value as double) as double; + operator |(value as double) as double; + operator ^(value as double) as double; + + operator +(value as double) as double; + operator -(value as double) as double; + operator *(value as double) as double; + operator /(value as double) as double; + operator %(value as double) as double; + + operator <(value as double) as bool; + operator >(value as double) as bool; + operator <=(value as double) as bool; + operator >=(value as double) as bool; + operator ==(value as double) as bool; + operator !=(value as double) as bool; + operator as() as byte, short, int, long, float, string; } diff --git a/packages/zenscript/src/builtins/float.dzs b/packages/zenscript/src/builtins/float.dzs index 9180895e..5c7d817b 100644 --- a/packages/zenscript/src/builtins/float.dzs +++ b/packages/zenscript/src/builtins/float.dzs @@ -1,4 +1,18 @@ zenClass float { operator -() as float; + + operator +(value as float) as float; + operator -(value as float) as float; + operator *(value as float) as float; + operator /(value as float) as float; + operator %(value as float) as float; + + operator <(value as float) as bool; + operator >(value as float) as bool; + operator <=(value as float) as bool; + operator >=(value as float) as bool; + operator ==(value as float) as bool; + operator !=(value as float) as bool; + operator as() as byte, short, int, long, double, string; } diff --git a/packages/zenscript/src/builtins/int.dzs b/packages/zenscript/src/builtins/int.dzs index 5a628648..28e1a270 100644 --- a/packages/zenscript/src/builtins/int.dzs +++ b/packages/zenscript/src/builtins/int.dzs @@ -1,4 +1,27 @@ +import stanhebben.zenscript.value.IntRange; + zenClass int { operator -() as int; + operator !() as int; + + operator &(value as int) as int; + operator |(value as int) as int; + operator ^(value as int) as int; + + operator +(value as int) as int; + operator -(value as int) as int; + operator *(value as int) as int; + operator /(value as int) as int; + operator %(value as int) as int; + + operator <(value as int) as bool; + operator >(value as int) as bool; + operator <=(value as int) as bool; + operator >=(value as int) as bool; + operator ==(value as int) as bool; + operator !=(value as int) as bool; + + operator ..(to as int) as IntRange; + operator as() as byte, short, long, float, double, string; } diff --git a/packages/zenscript/src/builtins/long.dzs b/packages/zenscript/src/builtins/long.dzs index 712d3c4b..df8c964c 100644 --- a/packages/zenscript/src/builtins/long.dzs +++ b/packages/zenscript/src/builtins/long.dzs @@ -1,4 +1,23 @@ zenClass long { operator -() as long; + operator !() as long; + + operator &(value as long) as long; + operator |(value as long) as long; + operator ^(value as long) as long; + + operator +(value as long) as long; + operator -(value as long) as long; + operator *(value as long) as long; + operator /(value as long) as long; + operator %(value as long) as long; + + operator <(value as long) as bool; + operator >(value as long) as bool; + operator <=(value as long) as bool; + operator >=(value as long) as bool; + operator ==(value as long) as bool; + operator !=(value as long) as bool; + operator as() as byte, short, int, float, double, string; } diff --git a/packages/zenscript/src/builtins/short.dzs b/packages/zenscript/src/builtins/short.dzs index 40d51158..85eb74b0 100644 --- a/packages/zenscript/src/builtins/short.dzs +++ b/packages/zenscript/src/builtins/short.dzs @@ -1,4 +1,23 @@ zenClass short { operator -() as short; + operator !() as short; + + operator &(value as short) as short; + operator |(value as short) as short; + operator ^(value as short) as short; + + operator +(value as short) as short; + operator -(value as short) as short; + operator *(value as short) as short; + operator /(value as short) as short; + operator %(value as short) as short; + + operator <(value as short) as bool; + operator >(value as short) as bool; + operator <=(value as short) as bool; + operator >=(value as short) as bool; + operator ==(value as any) as bool; + operator !=(value as any) as bool; + operator as() as byte, int, long, float, double, string; } diff --git a/packages/zenscript/src/builtins/string.dzs b/packages/zenscript/src/builtins/string.dzs index 9153871d..9a3818dc 100644 --- a/packages/zenscript/src/builtins/string.dzs +++ b/packages/zenscript/src/builtins/string.dzs @@ -87,5 +87,9 @@ zenClass string { operator +(value as string) as string; + operator has(substr as string) as bool; + + operator [](index as int) as string; + operator as() as bool, byte, int, short, long, float, double; } diff --git a/packages/zenscript/src/reference/member-provider.ts b/packages/zenscript/src/reference/member-provider.ts index cde086f4..5da1e2fa 100644 --- a/packages/zenscript/src/reference/member-provider.ts +++ b/packages/zenscript/src/reference/member-provider.ts @@ -1,10 +1,10 @@ import type { AstNode, Stream } from 'langium' -import type { ZenScriptAstType } from '../generated/ast' +import type { OperatorFunctionDeclaration, ZenScriptAstType } from '../generated/ast' import type { ZenScriptServices } from '../module' import type { TypeComputer } from '../typing/type-computer' import type { ZenScriptSyntheticAstType } from './synthetic' import { EMPTY_STREAM, stream } from 'langium' -import { isClassDeclaration, isVariableDeclaration } from '../generated/ast' +import { isClassDeclaration, isOperatorFunctionDeclaration, isVariableDeclaration } from '../generated/ast' import { ClassType, isAnyType, isClassType, isFunctionType, type Type, type ZenScriptType } from '../typing/type-description' import { isStatic, streamClassChain, streamDeclaredMembers } from '../utils/ast' import { defineRules } from '../utils/rule' @@ -12,6 +12,7 @@ import { isSyntheticAstNode } from './synthetic' export interface MemberProvider { streamMembers: (source: AstNode | Type | undefined) => Stream + streamOperators: (source: AstNode | Type | undefined) => Stream } type SourceMap = ZenScriptAstType & ZenScriptType & ZenScriptSyntheticAstType @@ -24,10 +25,14 @@ export class ZenScriptMemberProvider implements MemberProvider { this.typeComputer = services.typing.TypeComputer } - streamMembers(source: AstNode | Type | undefined): Stream { + public streamMembers(source: AstNode | Type | undefined): Stream { return this.rules(source?.$type)?.call(this, source) ?? EMPTY_STREAM } + public streamOperators(source: AstNode | Type | undefined): Stream { + return this.streamMembers(source).filter(isOperatorFunctionDeclaration) + } + private readonly rules = defineRules({ SyntheticHierarchyNode: (source) => { const declarations = stream(source.children.values()) diff --git a/packages/zenscript/src/typing/type-computer.ts b/packages/zenscript/src/typing/type-computer.ts index 10b9e87d..00630dd3 100644 --- a/packages/zenscript/src/typing/type-computer.ts +++ b/packages/zenscript/src/typing/type-computer.ts @@ -6,7 +6,7 @@ import type { BracketManager } from '../workspace/bracket-manager' import type { PackageManager } from '../workspace/package-manager' import type { BuiltinTypes, Type, TypeParameterSubstitutions } from './type-description' import { type AstNode, stream } from 'langium' -import { isAssignment, isCallExpression, isClassDeclaration, isExpression, isFunctionDeclaration, isFunctionExpression, isOperatorFunctionDeclaration, isTypeParameter, isVariableDeclaration } from '../generated/ast' +import { isAssignment, isCallExpression, isClassDeclaration, isExpression, isFunctionDeclaration, isFunctionExpression, isIndexingExpression, isOperatorFunctionDeclaration, isTypeParameter, isVariableDeclaration } from '../generated/ast' import { defineRules } from '../utils/rule' import { ClassType, CompoundType, FunctionType, IntersectionType, isAnyType, isClassType, isFunctionType, TypeVariable, UnionType } from './type-description' @@ -147,13 +147,12 @@ export class ZenScriptTypeComputer implements TypeComputer { return } - const operatorDecl = this.memberProvider().streamMembers(rangeType) - .filter(it => isOperatorFunctionDeclaration(it)) + const operator = this.memberProvider().streamOperators(rangeType) .filter(it => it.op === 'for') .filter(it => it.parameters.length === length) .head() - let paramType = this.inferType(operatorDecl?.parameters.at(index)) + let paramType = this.inferType(operator?.parameters.at(index)) if (isClassType(rangeType)) { paramType = paramType?.substituteTypeParameters(rangeType.substitutions) } @@ -202,7 +201,16 @@ export class ZenScriptTypeComputer implements TypeComputer { // region Expression Assignment: (source) => { - return this.inferType(source.right) + if (source.op === '=' && isIndexingExpression(source.left)) { + const operator = this.memberProvider().streamOperators(source.left.receiver) + .filter(it => it.op === '[]=') + .filter(it => it.parameters.length === 2) + .head() + return this.inferType(operator?.returnTypeRef) + } + else { + return this.inferType(source.right) + } }, ConditionalExpression: (source) => { @@ -211,52 +219,63 @@ export class ZenScriptTypeComputer implements TypeComputer { PrefixExpression: (source) => { switch (source.op) { - case '-': { - const operatorDecl = this.memberProvider().streamMembers(source.expr) - .filter(isOperatorFunctionDeclaration) - .filter(it => it.op === '-') + case '-': + case '!': { + const operator = this.memberProvider().streamOperators(source.expr) + .filter(it => it.op === source.op) .filter(it => it.parameters.length === 0) .head() - return this.inferType(operatorDecl?.returnTypeRef) + return this.inferType(operator?.returnTypeRef) } - - case '!': - return this.classTypeOf('bool') } }, InfixExpression: (source) => { - // TODO: operator overloading switch (source.op) { + case '&': // Arithmetic + case '|': + case '^': case '+': case '-': case '*': case '/': case '%': - return this.classTypeOf('int') - case '<': + case '<': // Comparison case '>': case '<=': case '>=': - return this.classTypeOf('bool') case '==': - case '!=': - return this.classTypeOf('bool') + case '!=': { + const operator = this.memberProvider().streamOperators(source.left) + .filter(it => it.op === source.op) + .filter(it => it.parameters.length === 1) + .head() + return this.inferType(operator?.returnTypeRef) + } + case 'has': // Containment + case 'in': { + const operator = this.memberProvider().streamOperators(source.left) + .filter(it => it.op === 'has') + .filter(it => it.parameters.length === 1) + .head() + return this.inferType(operator?.returnTypeRef) + } + case '..': // Range + case 'to': { + const operator = this.memberProvider().streamOperators(source.left) + .filter(it => it.op === '..') + .filter(it => it.parameters.length === 1) + .head() + return this.inferType(operator?.returnTypeRef) + } + // endregion + case '&&': case '||': return this.classTypeOf('bool') - case 'has': - case 'in': - return this.classTypeOf('bool') - case '&': - case '|': - case '^': - return this.classTypeOf('int') + case '~': return this.classTypeOf('string') - case 'to': - case '..': - return this.classTypeOf('stanhebben.zenscript.value.IntRange') } }, @@ -329,11 +348,11 @@ export class ZenScriptTypeComputer implements TypeComputer { return receiverType } - const operatorDecl = this.memberProvider().streamMembers(source.receiver) - .filter(it => isOperatorFunctionDeclaration(it)) + const operator = this.memberProvider().streamOperators(source.receiver) .filter(it => it.op === '[]') + .filter(it => it.parameters.length === 1) .head() - let returnType = this.inferType(operatorDecl?.returnTypeRef) + let returnType = this.inferType(operator?.returnTypeRef) if (isClassType(receiverType)) { returnType = returnType?.substituteTypeParameters(receiverType.substitutions) } From f9211ceb5273ab6f8dbf4ba29326d06628dea8ee Mon Sep 17 00:00:00 2001 From: raylras Date: Mon, 25 Nov 2024 18:40:22 +0800 Subject: [PATCH 06/11] minor --- packages/zenscript/src/typing/type-computer.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/zenscript/src/typing/type-computer.ts b/packages/zenscript/src/typing/type-computer.ts index 00630dd3..1997a726 100644 --- a/packages/zenscript/src/typing/type-computer.ts +++ b/packages/zenscript/src/typing/type-computer.ts @@ -268,7 +268,6 @@ export class ZenScriptTypeComputer implements TypeComputer { .head() return this.inferType(operator?.returnTypeRef) } - // endregion case '&&': case '||': From b39c6dac72d8d307fb09c36c20f1cf2276ac9cd6 Mon Sep 17 00:00:00 2001 From: raylras Date: Mon, 25 Nov 2024 18:44:16 +0800 Subject: [PATCH 07/11] fix: 'any' => 'short' --- packages/zenscript/src/builtins/short.dzs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/zenscript/src/builtins/short.dzs b/packages/zenscript/src/builtins/short.dzs index 85eb74b0..8940aee2 100644 --- a/packages/zenscript/src/builtins/short.dzs +++ b/packages/zenscript/src/builtins/short.dzs @@ -16,8 +16,8 @@ zenClass short { operator >(value as short) as bool; operator <=(value as short) as bool; operator >=(value as short) as bool; - operator ==(value as any) as bool; - operator !=(value as any) as bool; + operator ==(value as short) as bool; + operator !=(value as short) as bool; operator as() as byte, int, long, float, double, string; } From 065222ce97e6e8f88a4e1701c8e4557fe7cc023e Mon Sep 17 00:00:00 2001 From: raylras Date: Mon, 25 Nov 2024 21:16:02 +0800 Subject: [PATCH 08/11] add test for number operation --- packages/zenscript/src/builtins/double.dzs | 4 - .../test/typing/operator/intellizen.json | 5 + .../typing/operator/number-operation.test.ts | 466 ++++++++++++++++++ .../test/typing/operator/scripts/byte.zs | 21 + .../test/typing/operator/scripts/double.zs | 16 + .../test/typing/operator/scripts/float.zs | 16 + .../test/typing/operator/scripts/int.zs | 21 + .../test/typing/operator/scripts/long.zs | 21 + .../test/typing/operator/scripts/short.zs | 21 + 9 files changed, 587 insertions(+), 4 deletions(-) create mode 100644 packages/zenscript/test/typing/operator/intellizen.json create mode 100644 packages/zenscript/test/typing/operator/number-operation.test.ts create mode 100644 packages/zenscript/test/typing/operator/scripts/byte.zs create mode 100644 packages/zenscript/test/typing/operator/scripts/double.zs create mode 100644 packages/zenscript/test/typing/operator/scripts/float.zs create mode 100644 packages/zenscript/test/typing/operator/scripts/int.zs create mode 100644 packages/zenscript/test/typing/operator/scripts/long.zs create mode 100644 packages/zenscript/test/typing/operator/scripts/short.zs diff --git a/packages/zenscript/src/builtins/double.dzs b/packages/zenscript/src/builtins/double.dzs index 5542419c..cd26b15e 100644 --- a/packages/zenscript/src/builtins/double.dzs +++ b/packages/zenscript/src/builtins/double.dzs @@ -1,10 +1,6 @@ zenClass double { operator -() as double; - operator &(value as double) as double; - operator |(value as double) as double; - operator ^(value as double) as double; - operator +(value as double) as double; operator -(value as double) as double; operator *(value as double) as double; diff --git a/packages/zenscript/test/typing/operator/intellizen.json b/packages/zenscript/test/typing/operator/intellizen.json new file mode 100644 index 00000000..1e293b03 --- /dev/null +++ b/packages/zenscript/test/typing/operator/intellizen.json @@ -0,0 +1,5 @@ +{ + "srcRoots": [ + "./scripts" + ] +} diff --git a/packages/zenscript/test/typing/operator/number-operation.test.ts b/packages/zenscript/test/typing/operator/number-operation.test.ts new file mode 100644 index 00000000..358e4af3 --- /dev/null +++ b/packages/zenscript/test/typing/operator/number-operation.test.ts @@ -0,0 +1,466 @@ +import type { ExpressionStatement } from '../../../src/generated/ast' +import path from 'node:path' +import { describe, expect, it } from 'vitest' +import { assertNoErrors, createTestServices, getDocument } from '../../utils' + +const services = await createTestServices(__dirname) + +describe(`check operation of byte`, async () => { + const document_byte_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'byte.zs')) + const script_byte_zs = document_byte_zs.parseResult.value + let line = 0 + + it('syntax', () => { + assertNoErrors(document_byte_zs) + }) + + it('unary', () => { + const expr_neg = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_neg = services.typing.TypeComputer.inferType(expr_neg) + expect(type_neg?.toString()).toBe('byte') + + const expr_not = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_not = services.typing.TypeComputer.inferType(expr_not) + expect(type_not?.toString()).toBe('byte') + }) + + it('binary', () => { + // region Arithmetic + const expr_and = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_and = services.typing.TypeComputer.inferType(expr_and) + expect(type_and?.toString()).toBe('byte') + + const expr_or = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_or = services.typing.TypeComputer.inferType(expr_or) + expect(type_or?.toString()).toBe('byte') + + const expr_xor = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_xor = services.typing.TypeComputer.inferType(expr_xor) + expect(type_xor?.toString()).toBe('byte') + + const expr_add = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_add = services.typing.TypeComputer.inferType(expr_add) + expect(type_add?.toString()).toBe('byte') + + const expr_sub = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_sub = services.typing.TypeComputer.inferType(expr_sub) + expect(type_sub?.toString()).toBe('byte') + + const expr_mul = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_mul = services.typing.TypeComputer.inferType(expr_mul) + expect(type_mul?.toString()).toBe('byte') + + const expr_div = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_div = services.typing.TypeComputer.inferType(expr_div) + expect(type_div?.toString()).toBe('byte') + + const expr_mod = (script_byte_zs.statements[10] as ExpressionStatement).expr + const type_mod = services.typing.TypeComputer.inferType(expr_mod) + expect(type_mod?.toString()).toBe('byte') + // endregion + + // region Comparison + const expr_lt = (script_byte_zs.statements[11] as ExpressionStatement).expr + const type_lt = services.typing.TypeComputer.inferType(expr_lt) + expect(type_lt?.toString()).toBe('bool') + + const expr_gt = (script_byte_zs.statements[12] as ExpressionStatement).expr + const type_gt = services.typing.TypeComputer.inferType(expr_gt) + expect(type_gt?.toString()).toBe('bool') + + const expr_le = (script_byte_zs.statements[13] as ExpressionStatement).expr + const type_le = services.typing.TypeComputer.inferType(expr_le) + expect(type_le?.toString()).toBe('bool') + + const expr_ge = (script_byte_zs.statements[14] as ExpressionStatement).expr + const type_ge = services.typing.TypeComputer.inferType(expr_ge) + expect(type_ge?.toString()).toBe('bool') + + const expr_eq = (script_byte_zs.statements[15] as ExpressionStatement).expr + const type_eq = services.typing.TypeComputer.inferType(expr_eq) + expect(type_eq?.toString()).toBe('bool') + + const expr_nq = (script_byte_zs.statements[16] as ExpressionStatement).expr + const type_ne = services.typing.TypeComputer.inferType(expr_nq) + expect(type_ne?.toString()).toBe('bool') + // endregion + }) +}) + +describe(`check operation of short`, async () => { + const document_short_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'short.zs')) + const script_short_zs = document_short_zs.parseResult.value + let line = 0 + + it('syntax', () => { + assertNoErrors(document_short_zs) + }) + + it('unary', () => { + const expr_neg = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_neg = services.typing.TypeComputer.inferType(expr_neg) + expect(type_neg?.toString()).toBe('short') + + const expr_not = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_not = services.typing.TypeComputer.inferType(expr_not) + expect(type_not?.toString()).toBe('short') + }) + + it('binary', () => { + // region Arithmetic + const expr_and = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_and = services.typing.TypeComputer.inferType(expr_and) + expect(type_and?.toString()).toBe('short') + + const expr_or = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_or = services.typing.TypeComputer.inferType(expr_or) + expect(type_or?.toString()).toBe('short') + + const expr_xor = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_xor = services.typing.TypeComputer.inferType(expr_xor) + expect(type_xor?.toString()).toBe('short') + + const expr_add = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_add = services.typing.TypeComputer.inferType(expr_add) + expect(type_add?.toString()).toBe('short') + + const expr_sub = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_sub = services.typing.TypeComputer.inferType(expr_sub) + expect(type_sub?.toString()).toBe('short') + + const expr_mul = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_mul = services.typing.TypeComputer.inferType(expr_mul) + expect(type_mul?.toString()).toBe('short') + + const expr_div = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_div = services.typing.TypeComputer.inferType(expr_div) + expect(type_div?.toString()).toBe('short') + + const expr_mod = (script_short_zs.statements[10] as ExpressionStatement).expr + const type_mod = services.typing.TypeComputer.inferType(expr_mod) + expect(type_mod?.toString()).toBe('short') + // endregion + + // region Comparison + const expr_lt = (script_short_zs.statements[11] as ExpressionStatement).expr + const type_lt = services.typing.TypeComputer.inferType(expr_lt) + expect(type_lt?.toString()).toBe('bool') + + const expr_gt = (script_short_zs.statements[12] as ExpressionStatement).expr + const type_gt = services.typing.TypeComputer.inferType(expr_gt) + expect(type_gt?.toString()).toBe('bool') + + const expr_le = (script_short_zs.statements[13] as ExpressionStatement).expr + const type_le = services.typing.TypeComputer.inferType(expr_le) + expect(type_le?.toString()).toBe('bool') + + const expr_ge = (script_short_zs.statements[14] as ExpressionStatement).expr + const type_ge = services.typing.TypeComputer.inferType(expr_ge) + expect(type_ge?.toString()).toBe('bool') + + const expr_eq = (script_short_zs.statements[15] as ExpressionStatement).expr + const type_eq = services.typing.TypeComputer.inferType(expr_eq) + expect(type_eq?.toString()).toBe('bool') + + const expr_nq = (script_short_zs.statements[16] as ExpressionStatement).expr + const type_ne = services.typing.TypeComputer.inferType(expr_nq) + expect(type_ne?.toString()).toBe('bool') + // endregion + }) +}) + +describe(`check operation of int`, async () => { + const document_int_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'int.zs')) + const script_int_zs = document_int_zs.parseResult.value + let line = 0 + + it('syntax', () => { + assertNoErrors(document_int_zs) + }) + + it('unary', () => { + const expr_neg = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_neg = services.typing.TypeComputer.inferType(expr_neg) + expect(type_neg?.toString()).toBe('int') + + const expr_not = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_not = services.typing.TypeComputer.inferType(expr_not) + expect(type_not?.toString()).toBe('int') + }) + + it('binary', () => { + // region Arithmetic + const expr_and = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_and = services.typing.TypeComputer.inferType(expr_and) + expect(type_and?.toString()).toBe('int') + + const expr_or = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_or = services.typing.TypeComputer.inferType(expr_or) + expect(type_or?.toString()).toBe('int') + + const expr_xor = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_xor = services.typing.TypeComputer.inferType(expr_xor) + expect(type_xor?.toString()).toBe('int') + + const expr_add = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_add = services.typing.TypeComputer.inferType(expr_add) + expect(type_add?.toString()).toBe('int') + + const expr_sub = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_sub = services.typing.TypeComputer.inferType(expr_sub) + expect(type_sub?.toString()).toBe('int') + + const expr_mul = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_mul = services.typing.TypeComputer.inferType(expr_mul) + expect(type_mul?.toString()).toBe('int') + + const expr_div = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_div = services.typing.TypeComputer.inferType(expr_div) + expect(type_div?.toString()).toBe('int') + + const expr_mod = (script_int_zs.statements[10] as ExpressionStatement).expr + const type_mod = services.typing.TypeComputer.inferType(expr_mod) + expect(type_mod?.toString()).toBe('int') + // endregion + + // region Comparison + const expr_lt = (script_int_zs.statements[11] as ExpressionStatement).expr + const type_lt = services.typing.TypeComputer.inferType(expr_lt) + expect(type_lt?.toString()).toBe('bool') + + const expr_gt = (script_int_zs.statements[12] as ExpressionStatement).expr + const type_gt = services.typing.TypeComputer.inferType(expr_gt) + expect(type_gt?.toString()).toBe('bool') + + const expr_le = (script_int_zs.statements[13] as ExpressionStatement).expr + const type_le = services.typing.TypeComputer.inferType(expr_le) + expect(type_le?.toString()).toBe('bool') + + const expr_ge = (script_int_zs.statements[14] as ExpressionStatement).expr + const type_ge = services.typing.TypeComputer.inferType(expr_ge) + expect(type_ge?.toString()).toBe('bool') + + const expr_eq = (script_int_zs.statements[15] as ExpressionStatement).expr + const type_eq = services.typing.TypeComputer.inferType(expr_eq) + expect(type_eq?.toString()).toBe('bool') + + const expr_nq = (script_int_zs.statements[16] as ExpressionStatement).expr + const type_ne = services.typing.TypeComputer.inferType(expr_nq) + expect(type_ne?.toString()).toBe('bool') + // endregion + }) +}) + +describe(`check operation of long`, async () => { + const document_long_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'long.zs')) + const script_long_zs = document_long_zs.parseResult.value + let line = 0 + + it('syntax', () => { + assertNoErrors(document_long_zs) + }) + + it('unary', () => { + const expr_neg = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_neg = services.typing.TypeComputer.inferType(expr_neg) + expect(type_neg?.toString()).toBe('long') + + const expr_not = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_not = services.typing.TypeComputer.inferType(expr_not) + expect(type_not?.toString()).toBe('long') + }) + + it('binary', () => { + // region Arithmetic + const expr_and = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_and = services.typing.TypeComputer.inferType(expr_and) + expect(type_and?.toString()).toBe('long') + + const expr_or = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_or = services.typing.TypeComputer.inferType(expr_or) + expect(type_or?.toString()).toBe('long') + + const expr_xor = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_xor = services.typing.TypeComputer.inferType(expr_xor) + expect(type_xor?.toString()).toBe('long') + + const expr_add = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_add = services.typing.TypeComputer.inferType(expr_add) + expect(type_add?.toString()).toBe('long') + + const expr_sub = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_sub = services.typing.TypeComputer.inferType(expr_sub) + expect(type_sub?.toString()).toBe('long') + + const expr_mul = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_mul = services.typing.TypeComputer.inferType(expr_mul) + expect(type_mul?.toString()).toBe('long') + + const expr_div = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_div = services.typing.TypeComputer.inferType(expr_div) + expect(type_div?.toString()).toBe('long') + + const expr_mod = (script_long_zs.statements[10] as ExpressionStatement).expr + const type_mod = services.typing.TypeComputer.inferType(expr_mod) + expect(type_mod?.toString()).toBe('long') + // endregion + + // region Comparison + const expr_lt = (script_long_zs.statements[11] as ExpressionStatement).expr + const type_lt = services.typing.TypeComputer.inferType(expr_lt) + expect(type_lt?.toString()).toBe('bool') + + const expr_gt = (script_long_zs.statements[12] as ExpressionStatement).expr + const type_gt = services.typing.TypeComputer.inferType(expr_gt) + expect(type_gt?.toString()).toBe('bool') + + const expr_le = (script_long_zs.statements[13] as ExpressionStatement).expr + const type_le = services.typing.TypeComputer.inferType(expr_le) + expect(type_le?.toString()).toBe('bool') + + const expr_ge = (script_long_zs.statements[14] as ExpressionStatement).expr + const type_ge = services.typing.TypeComputer.inferType(expr_ge) + expect(type_ge?.toString()).toBe('bool') + + const expr_eq = (script_long_zs.statements[15] as ExpressionStatement).expr + const type_eq = services.typing.TypeComputer.inferType(expr_eq) + expect(type_eq?.toString()).toBe('bool') + + const expr_nq = (script_long_zs.statements[16] as ExpressionStatement).expr + const type_ne = services.typing.TypeComputer.inferType(expr_nq) + expect(type_ne?.toString()).toBe('bool') + // endregion + }) +}) + +describe(`check operation of float`, async () => { + const document_float_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'float.zs')) + const script_float_zs = document_float_zs.parseResult.value + let line = 0 + + it('syntax', () => { + assertNoErrors(document_float_zs) + }) + + it('unary', () => { + const expr_neg = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_neg = services.typing.TypeComputer.inferType(expr_neg) + expect(type_neg?.toString()).toBe('float') + }) + + it('binary', () => { + // region Arithmetic + const expr_add = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_add = services.typing.TypeComputer.inferType(expr_add) + expect(type_add?.toString()).toBe('float') + + const expr_sub = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_sub = services.typing.TypeComputer.inferType(expr_sub) + expect(type_sub?.toString()).toBe('float') + + const expr_mul = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_mul = services.typing.TypeComputer.inferType(expr_mul) + expect(type_mul?.toString()).toBe('float') + + const expr_div = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_div = services.typing.TypeComputer.inferType(expr_div) + expect(type_div?.toString()).toBe('float') + + const expr_mod = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_mod = services.typing.TypeComputer.inferType(expr_mod) + expect(type_mod?.toString()).toBe('float') + // endregion + + // region Comparison + const expr_lt = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_lt = services.typing.TypeComputer.inferType(expr_lt) + expect(type_lt?.toString()).toBe('bool') + + const expr_gt = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_gt = services.typing.TypeComputer.inferType(expr_gt) + expect(type_gt?.toString()).toBe('bool') + + const expr_le = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_le = services.typing.TypeComputer.inferType(expr_le) + expect(type_le?.toString()).toBe('bool') + + const expr_ge = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_ge = services.typing.TypeComputer.inferType(expr_ge) + expect(type_ge?.toString()).toBe('bool') + + const expr_eq = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_eq = services.typing.TypeComputer.inferType(expr_eq) + expect(type_eq?.toString()).toBe('bool') + + const expr_nq = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_ne = services.typing.TypeComputer.inferType(expr_nq) + expect(type_ne?.toString()).toBe('bool') + // endregion + }) +}) + +describe(`check operation of double`, async () => { + const document_double_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'double.zs')) + const script_double_zs = document_double_zs.parseResult.value + let line = 0 + + it('syntax', () => { + assertNoErrors(document_double_zs) + }) + + it('unary', () => { + const expr_neg = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_neg = services.typing.TypeComputer.inferType(expr_neg) + expect(type_neg?.toString()).toBe('double') + }) + + it('binary', () => { + // region Arithmetic + const expr_add = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_add = services.typing.TypeComputer.inferType(expr_add) + expect(type_add?.toString()).toBe('double') + + const expr_sub = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_sub = services.typing.TypeComputer.inferType(expr_sub) + expect(type_sub?.toString()).toBe('double') + + const expr_mul = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_mul = services.typing.TypeComputer.inferType(expr_mul) + expect(type_mul?.toString()).toBe('double') + + const expr_div = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_div = services.typing.TypeComputer.inferType(expr_div) + expect(type_div?.toString()).toBe('double') + + const expr_mod = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_mod = services.typing.TypeComputer.inferType(expr_mod) + expect(type_mod?.toString()).toBe('double') + // endregion + + // region Comparison + const expr_lt = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_lt = services.typing.TypeComputer.inferType(expr_lt) + expect(type_lt?.toString()).toBe('bool') + + const expr_gt = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_gt = services.typing.TypeComputer.inferType(expr_gt) + expect(type_gt?.toString()).toBe('bool') + + const expr_le = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_le = services.typing.TypeComputer.inferType(expr_le) + expect(type_le?.toString()).toBe('bool') + + const expr_ge = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_ge = services.typing.TypeComputer.inferType(expr_ge) + expect(type_ge?.toString()).toBe('bool') + + const expr_eq = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_eq = services.typing.TypeComputer.inferType(expr_eq) + expect(type_eq?.toString()).toBe('bool') + + const expr_nq = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_ne = services.typing.TypeComputer.inferType(expr_nq) + expect(type_ne?.toString()).toBe('bool') + // endregion + }) +}) diff --git a/packages/zenscript/test/typing/operator/scripts/byte.zs b/packages/zenscript/test/typing/operator/scripts/byte.zs new file mode 100644 index 00000000..e176bd8f --- /dev/null +++ b/packages/zenscript/test/typing/operator/scripts/byte.zs @@ -0,0 +1,21 @@ +val one = 1 as byte; + +-one; +!one; + +one & one; +one | one; +one ^ one; + +one + one; +one - one; +one * one; +one / one; +one % one; + +one < one; +one > one; +one <= one; +one >= one; +one == one; +one != one; diff --git a/packages/zenscript/test/typing/operator/scripts/double.zs b/packages/zenscript/test/typing/operator/scripts/double.zs new file mode 100644 index 00000000..3fa3cccf --- /dev/null +++ b/packages/zenscript/test/typing/operator/scripts/double.zs @@ -0,0 +1,16 @@ +val one = 1.0D as double; + +-one; + +one + one; +one - one; +one * one; +one / one; +one % one; + +one < one; +one > one; +one <= one; +one >= one; +one == one; +one != one; diff --git a/packages/zenscript/test/typing/operator/scripts/float.zs b/packages/zenscript/test/typing/operator/scripts/float.zs new file mode 100644 index 00000000..5d4473ad --- /dev/null +++ b/packages/zenscript/test/typing/operator/scripts/float.zs @@ -0,0 +1,16 @@ +val one = 1.0f as float; + +-one; + +one + one; +one - one; +one * one; +one / one; +one % one; + +one < one; +one > one; +one <= one; +one >= one; +one == one; +one != one; diff --git a/packages/zenscript/test/typing/operator/scripts/int.zs b/packages/zenscript/test/typing/operator/scripts/int.zs new file mode 100644 index 00000000..e359c1e1 --- /dev/null +++ b/packages/zenscript/test/typing/operator/scripts/int.zs @@ -0,0 +1,21 @@ +val one = 1 as int; + +-one; +!one; + +one & one; +one | one; +one ^ one; + +one + one; +one - one; +one * one; +one / one; +one % one; + +one < one; +one > one; +one <= one; +one >= one; +one == one; +one != one; diff --git a/packages/zenscript/test/typing/operator/scripts/long.zs b/packages/zenscript/test/typing/operator/scripts/long.zs new file mode 100644 index 00000000..8f18e11c --- /dev/null +++ b/packages/zenscript/test/typing/operator/scripts/long.zs @@ -0,0 +1,21 @@ +val one = 1L as long; + +-one; +!one; + +one & one; +one | one; +one ^ one; + +one + one; +one - one; +one * one; +one / one; +one % one; + +one < one; +one > one; +one <= one; +one >= one; +one == one; +one != one; diff --git a/packages/zenscript/test/typing/operator/scripts/short.zs b/packages/zenscript/test/typing/operator/scripts/short.zs new file mode 100644 index 00000000..05a6ae08 --- /dev/null +++ b/packages/zenscript/test/typing/operator/scripts/short.zs @@ -0,0 +1,21 @@ +val one = 1 as short; + +-one; +!one; + +one & one; +one | one; +one ^ one; + +one + one; +one - one; +one * one; +one / one; +one % one; + +one < one; +one > one; +one <= one; +one >= one; +one == one; +one != one; From 95cb13727be512284afd3fb75ced7192fb2c80a4 Mon Sep 17 00:00:00 2001 From: raylras Date: Mon, 25 Nov 2024 21:51:35 +0800 Subject: [PATCH 09/11] improve test --- .../typing/operator/number-operation.test.ts | 930 +++++++++++------- 1 file changed, 553 insertions(+), 377 deletions(-) diff --git a/packages/zenscript/test/typing/operator/number-operation.test.ts b/packages/zenscript/test/typing/operator/number-operation.test.ts index 358e4af3..0352517b 100644 --- a/packages/zenscript/test/typing/operator/number-operation.test.ts +++ b/packages/zenscript/test/typing/operator/number-operation.test.ts @@ -1,6 +1,6 @@ import type { ExpressionStatement } from '../../../src/generated/ast' import path from 'node:path' -import { describe, expect, it } from 'vitest' +import { describe, expect, it, suite } from 'vitest' import { assertNoErrors, createTestServices, getDocument } from '../../utils' const services = await createTestServices(__dirname) @@ -14,76 +14,108 @@ describe(`check operation of byte`, async () => { assertNoErrors(document_byte_zs) }) - it('unary', () => { - const expr_neg = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_neg = services.typing.TypeComputer.inferType(expr_neg) - expect(type_neg?.toString()).toBe('byte') - - const expr_not = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_not = services.typing.TypeComputer.inferType(expr_not) - expect(type_not?.toString()).toBe('byte') + suite('unary', () => { + it('-', () => { + const expr_neg = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_neg = services.typing.TypeComputer.inferType(expr_neg) + expect(type_neg?.toString()).toBe('byte') + }) + + it('!', () => { + const expr_not = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_not = services.typing.TypeComputer.inferType(expr_not) + expect(type_not?.toString()).toBe('byte') + }) }) - it('binary', () => { - // region Arithmetic - const expr_and = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_and = services.typing.TypeComputer.inferType(expr_and) - expect(type_and?.toString()).toBe('byte') - - const expr_or = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_or = services.typing.TypeComputer.inferType(expr_or) - expect(type_or?.toString()).toBe('byte') - - const expr_xor = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_xor = services.typing.TypeComputer.inferType(expr_xor) - expect(type_xor?.toString()).toBe('byte') - - const expr_add = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_add = services.typing.TypeComputer.inferType(expr_add) - expect(type_add?.toString()).toBe('byte') - - const expr_sub = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_sub = services.typing.TypeComputer.inferType(expr_sub) - expect(type_sub?.toString()).toBe('byte') - - const expr_mul = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_mul = services.typing.TypeComputer.inferType(expr_mul) - expect(type_mul?.toString()).toBe('byte') - - const expr_div = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_div = services.typing.TypeComputer.inferType(expr_div) - expect(type_div?.toString()).toBe('byte') - - const expr_mod = (script_byte_zs.statements[10] as ExpressionStatement).expr - const type_mod = services.typing.TypeComputer.inferType(expr_mod) - expect(type_mod?.toString()).toBe('byte') - // endregion - - // region Comparison - const expr_lt = (script_byte_zs.statements[11] as ExpressionStatement).expr - const type_lt = services.typing.TypeComputer.inferType(expr_lt) - expect(type_lt?.toString()).toBe('bool') - - const expr_gt = (script_byte_zs.statements[12] as ExpressionStatement).expr - const type_gt = services.typing.TypeComputer.inferType(expr_gt) - expect(type_gt?.toString()).toBe('bool') - - const expr_le = (script_byte_zs.statements[13] as ExpressionStatement).expr - const type_le = services.typing.TypeComputer.inferType(expr_le) - expect(type_le?.toString()).toBe('bool') - - const expr_ge = (script_byte_zs.statements[14] as ExpressionStatement).expr - const type_ge = services.typing.TypeComputer.inferType(expr_ge) - expect(type_ge?.toString()).toBe('bool') - - const expr_eq = (script_byte_zs.statements[15] as ExpressionStatement).expr - const type_eq = services.typing.TypeComputer.inferType(expr_eq) - expect(type_eq?.toString()).toBe('bool') - - const expr_nq = (script_byte_zs.statements[16] as ExpressionStatement).expr - const type_ne = services.typing.TypeComputer.inferType(expr_nq) - expect(type_ne?.toString()).toBe('bool') - // endregion + suite('binary', () => { + suite('arithmetic', () => { + it('&', () => { + const expr_and = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_and = services.typing.TypeComputer.inferType(expr_and) + expect(type_and?.toString()).toBe('byte') + }) + + it('|', () => { + const expr_or = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_or = services.typing.TypeComputer.inferType(expr_or) + expect(type_or?.toString()).toBe('byte') + }) + + it('^', () => { + const expr_xor = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_xor = services.typing.TypeComputer.inferType(expr_xor) + expect(type_xor?.toString()).toBe('byte') + }) + + it('+', () => { + const expr_add = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_add = services.typing.TypeComputer.inferType(expr_add) + expect(type_add?.toString()).toBe('byte') + }) + + it('-', () => { + const expr_sub = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_sub = services.typing.TypeComputer.inferType(expr_sub) + expect(type_sub?.toString()).toBe('byte') + }) + + it('*', () => { + const expr_mul = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_mul = services.typing.TypeComputer.inferType(expr_mul) + expect(type_mul?.toString()).toBe('byte') + }) + + it('/', () => { + const expr_div = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_div = services.typing.TypeComputer.inferType(expr_div) + expect(type_div?.toString()).toBe('byte') + }) + + it('%', () => { + const expr_mod = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_mod = services.typing.TypeComputer.inferType(expr_mod) + expect(type_mod?.toString()).toBe('byte') + }) + }) + + suite('comparison', () => { + it('<', () => { + const expr_lt = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_lt = services.typing.TypeComputer.inferType(expr_lt) + expect(type_lt?.toString()).toBe('bool') + }) + + it('>', () => { + const expr_gt = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_gt = services.typing.TypeComputer.inferType(expr_gt) + expect(type_gt?.toString()).toBe('bool') + }) + + it('<=', () => { + const expr_le = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_le = services.typing.TypeComputer.inferType(expr_le) + expect(type_le?.toString()).toBe('bool') + }) + + it('>=', () => { + const expr_ge = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_ge = services.typing.TypeComputer.inferType(expr_ge) + expect(type_ge?.toString()).toBe('bool') + }) + + it('==', () => { + const expr_eq = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_eq = services.typing.TypeComputer.inferType(expr_eq) + expect(type_eq?.toString()).toBe('bool') + }) + + it('!=', () => { + const expr_nq = (script_byte_zs.statements[++line] as ExpressionStatement).expr + const type_ne = services.typing.TypeComputer.inferType(expr_nq) + expect(type_ne?.toString()).toBe('bool') + }) + }) }) }) @@ -96,76 +128,108 @@ describe(`check operation of short`, async () => { assertNoErrors(document_short_zs) }) - it('unary', () => { - const expr_neg = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_neg = services.typing.TypeComputer.inferType(expr_neg) - expect(type_neg?.toString()).toBe('short') - - const expr_not = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_not = services.typing.TypeComputer.inferType(expr_not) - expect(type_not?.toString()).toBe('short') + suite('unary', () => { + it('-', () => { + const expr_neg = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_neg = services.typing.TypeComputer.inferType(expr_neg) + expect(type_neg?.toString()).toBe('short') + }) + + it('!', () => { + const expr_not = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_not = services.typing.TypeComputer.inferType(expr_not) + expect(type_not?.toString()).toBe('short') + }) }) - it('binary', () => { - // region Arithmetic - const expr_and = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_and = services.typing.TypeComputer.inferType(expr_and) - expect(type_and?.toString()).toBe('short') - - const expr_or = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_or = services.typing.TypeComputer.inferType(expr_or) - expect(type_or?.toString()).toBe('short') - - const expr_xor = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_xor = services.typing.TypeComputer.inferType(expr_xor) - expect(type_xor?.toString()).toBe('short') - - const expr_add = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_add = services.typing.TypeComputer.inferType(expr_add) - expect(type_add?.toString()).toBe('short') - - const expr_sub = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_sub = services.typing.TypeComputer.inferType(expr_sub) - expect(type_sub?.toString()).toBe('short') - - const expr_mul = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_mul = services.typing.TypeComputer.inferType(expr_mul) - expect(type_mul?.toString()).toBe('short') - - const expr_div = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_div = services.typing.TypeComputer.inferType(expr_div) - expect(type_div?.toString()).toBe('short') - - const expr_mod = (script_short_zs.statements[10] as ExpressionStatement).expr - const type_mod = services.typing.TypeComputer.inferType(expr_mod) - expect(type_mod?.toString()).toBe('short') - // endregion - - // region Comparison - const expr_lt = (script_short_zs.statements[11] as ExpressionStatement).expr - const type_lt = services.typing.TypeComputer.inferType(expr_lt) - expect(type_lt?.toString()).toBe('bool') - - const expr_gt = (script_short_zs.statements[12] as ExpressionStatement).expr - const type_gt = services.typing.TypeComputer.inferType(expr_gt) - expect(type_gt?.toString()).toBe('bool') - - const expr_le = (script_short_zs.statements[13] as ExpressionStatement).expr - const type_le = services.typing.TypeComputer.inferType(expr_le) - expect(type_le?.toString()).toBe('bool') - - const expr_ge = (script_short_zs.statements[14] as ExpressionStatement).expr - const type_ge = services.typing.TypeComputer.inferType(expr_ge) - expect(type_ge?.toString()).toBe('bool') - - const expr_eq = (script_short_zs.statements[15] as ExpressionStatement).expr - const type_eq = services.typing.TypeComputer.inferType(expr_eq) - expect(type_eq?.toString()).toBe('bool') - - const expr_nq = (script_short_zs.statements[16] as ExpressionStatement).expr - const type_ne = services.typing.TypeComputer.inferType(expr_nq) - expect(type_ne?.toString()).toBe('bool') - // endregion + suite('binary', () => { + suite('arithmetic', () => { + it('&', () => { + const expr_and = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_and = services.typing.TypeComputer.inferType(expr_and) + expect(type_and?.toString()).toBe('short') + }) + + it('|', () => { + const expr_or = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_or = services.typing.TypeComputer.inferType(expr_or) + expect(type_or?.toString()).toBe('short') + }) + + it('^', () => { + const expr_xor = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_xor = services.typing.TypeComputer.inferType(expr_xor) + expect(type_xor?.toString()).toBe('short') + }) + + it('+', () => { + const expr_add = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_add = services.typing.TypeComputer.inferType(expr_add) + expect(type_add?.toString()).toBe('short') + }) + + it('-', () => { + const expr_sub = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_sub = services.typing.TypeComputer.inferType(expr_sub) + expect(type_sub?.toString()).toBe('short') + }) + + it('*', () => { + const expr_mul = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_mul = services.typing.TypeComputer.inferType(expr_mul) + expect(type_mul?.toString()).toBe('short') + }) + + it('/', () => { + const expr_div = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_div = services.typing.TypeComputer.inferType(expr_div) + expect(type_div?.toString()).toBe('short') + }) + + it('%', () => { + const expr_mod = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_mod = services.typing.TypeComputer.inferType(expr_mod) + expect(type_mod?.toString()).toBe('short') + }) + }) + + suite('comparison', () => { + it('<', () => { + const expr_lt = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_lt = services.typing.TypeComputer.inferType(expr_lt) + expect(type_lt?.toString()).toBe('bool') + }) + + it('>', () => { + const expr_gt = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_gt = services.typing.TypeComputer.inferType(expr_gt) + expect(type_gt?.toString()).toBe('bool') + }) + + it('<=', () => { + const expr_le = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_le = services.typing.TypeComputer.inferType(expr_le) + expect(type_le?.toString()).toBe('bool') + }) + + it('>=', () => { + const expr_ge = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_ge = services.typing.TypeComputer.inferType(expr_ge) + expect(type_ge?.toString()).toBe('bool') + }) + + it('==', () => { + const expr_eq = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_eq = services.typing.TypeComputer.inferType(expr_eq) + expect(type_eq?.toString()).toBe('bool') + }) + + it('!=', () => { + const expr_nq = (script_short_zs.statements[++line] as ExpressionStatement).expr + const type_ne = services.typing.TypeComputer.inferType(expr_nq) + expect(type_ne?.toString()).toBe('bool') + }) + }) }) }) @@ -178,76 +242,108 @@ describe(`check operation of int`, async () => { assertNoErrors(document_int_zs) }) - it('unary', () => { - const expr_neg = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_neg = services.typing.TypeComputer.inferType(expr_neg) - expect(type_neg?.toString()).toBe('int') - - const expr_not = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_not = services.typing.TypeComputer.inferType(expr_not) - expect(type_not?.toString()).toBe('int') + suite('unary', () => { + it('-', () => { + const expr_neg = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_neg = services.typing.TypeComputer.inferType(expr_neg) + expect(type_neg?.toString()).toBe('int') + }) + + it('!', () => { + const expr_not = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_not = services.typing.TypeComputer.inferType(expr_not) + expect(type_not?.toString()).toBe('int') + }) }) - it('binary', () => { - // region Arithmetic - const expr_and = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_and = services.typing.TypeComputer.inferType(expr_and) - expect(type_and?.toString()).toBe('int') - - const expr_or = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_or = services.typing.TypeComputer.inferType(expr_or) - expect(type_or?.toString()).toBe('int') - - const expr_xor = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_xor = services.typing.TypeComputer.inferType(expr_xor) - expect(type_xor?.toString()).toBe('int') - - const expr_add = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_add = services.typing.TypeComputer.inferType(expr_add) - expect(type_add?.toString()).toBe('int') - - const expr_sub = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_sub = services.typing.TypeComputer.inferType(expr_sub) - expect(type_sub?.toString()).toBe('int') - - const expr_mul = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_mul = services.typing.TypeComputer.inferType(expr_mul) - expect(type_mul?.toString()).toBe('int') - - const expr_div = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_div = services.typing.TypeComputer.inferType(expr_div) - expect(type_div?.toString()).toBe('int') - - const expr_mod = (script_int_zs.statements[10] as ExpressionStatement).expr - const type_mod = services.typing.TypeComputer.inferType(expr_mod) - expect(type_mod?.toString()).toBe('int') - // endregion - - // region Comparison - const expr_lt = (script_int_zs.statements[11] as ExpressionStatement).expr - const type_lt = services.typing.TypeComputer.inferType(expr_lt) - expect(type_lt?.toString()).toBe('bool') - - const expr_gt = (script_int_zs.statements[12] as ExpressionStatement).expr - const type_gt = services.typing.TypeComputer.inferType(expr_gt) - expect(type_gt?.toString()).toBe('bool') - - const expr_le = (script_int_zs.statements[13] as ExpressionStatement).expr - const type_le = services.typing.TypeComputer.inferType(expr_le) - expect(type_le?.toString()).toBe('bool') - - const expr_ge = (script_int_zs.statements[14] as ExpressionStatement).expr - const type_ge = services.typing.TypeComputer.inferType(expr_ge) - expect(type_ge?.toString()).toBe('bool') - - const expr_eq = (script_int_zs.statements[15] as ExpressionStatement).expr - const type_eq = services.typing.TypeComputer.inferType(expr_eq) - expect(type_eq?.toString()).toBe('bool') - - const expr_nq = (script_int_zs.statements[16] as ExpressionStatement).expr - const type_ne = services.typing.TypeComputer.inferType(expr_nq) - expect(type_ne?.toString()).toBe('bool') - // endregion + suite('binary', () => { + suite('arithmetic', () => { + it('&', () => { + const expr_and = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_and = services.typing.TypeComputer.inferType(expr_and) + expect(type_and?.toString()).toBe('int') + }) + + it('|', () => { + const expr_or = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_or = services.typing.TypeComputer.inferType(expr_or) + expect(type_or?.toString()).toBe('int') + }) + + it('^', () => { + const expr_xor = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_xor = services.typing.TypeComputer.inferType(expr_xor) + expect(type_xor?.toString()).toBe('int') + }) + + it('+', () => { + const expr_add = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_add = services.typing.TypeComputer.inferType(expr_add) + expect(type_add?.toString()).toBe('int') + }) + + it('-', () => { + const expr_sub = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_sub = services.typing.TypeComputer.inferType(expr_sub) + expect(type_sub?.toString()).toBe('int') + }) + + it('*', () => { + const expr_mul = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_mul = services.typing.TypeComputer.inferType(expr_mul) + expect(type_mul?.toString()).toBe('int') + }) + + it('/', () => { + const expr_div = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_div = services.typing.TypeComputer.inferType(expr_div) + expect(type_div?.toString()).toBe('int') + }) + + it('%', () => { + const expr_mod = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_mod = services.typing.TypeComputer.inferType(expr_mod) + expect(type_mod?.toString()).toBe('int') + }) + }) + + suite('comparison', () => { + it('<', () => { + const expr_lt = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_lt = services.typing.TypeComputer.inferType(expr_lt) + expect(type_lt?.toString()).toBe('bool') + }) + + it('>', () => { + const expr_gt = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_gt = services.typing.TypeComputer.inferType(expr_gt) + expect(type_gt?.toString()).toBe('bool') + }) + + it('<=', () => { + const expr_le = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_le = services.typing.TypeComputer.inferType(expr_le) + expect(type_le?.toString()).toBe('bool') + }) + + it('>=', () => { + const expr_ge = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_ge = services.typing.TypeComputer.inferType(expr_ge) + expect(type_ge?.toString()).toBe('bool') + }) + + it('==', () => { + const expr_eq = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_eq = services.typing.TypeComputer.inferType(expr_eq) + expect(type_eq?.toString()).toBe('bool') + }) + + it('!=', () => { + const expr_nq = (script_int_zs.statements[++line] as ExpressionStatement).expr + const type_ne = services.typing.TypeComputer.inferType(expr_nq) + expect(type_ne?.toString()).toBe('bool') + }) + }) }) }) @@ -260,76 +356,108 @@ describe(`check operation of long`, async () => { assertNoErrors(document_long_zs) }) - it('unary', () => { - const expr_neg = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_neg = services.typing.TypeComputer.inferType(expr_neg) - expect(type_neg?.toString()).toBe('long') - - const expr_not = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_not = services.typing.TypeComputer.inferType(expr_not) - expect(type_not?.toString()).toBe('long') + suite('unary', () => { + it('-', () => { + const expr_neg = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_neg = services.typing.TypeComputer.inferType(expr_neg) + expect(type_neg?.toString()).toBe('long') + }) + + it('!', () => { + const expr_not = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_not = services.typing.TypeComputer.inferType(expr_not) + expect(type_not?.toString()).toBe('long') + }) }) - it('binary', () => { - // region Arithmetic - const expr_and = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_and = services.typing.TypeComputer.inferType(expr_and) - expect(type_and?.toString()).toBe('long') - - const expr_or = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_or = services.typing.TypeComputer.inferType(expr_or) - expect(type_or?.toString()).toBe('long') - - const expr_xor = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_xor = services.typing.TypeComputer.inferType(expr_xor) - expect(type_xor?.toString()).toBe('long') - - const expr_add = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_add = services.typing.TypeComputer.inferType(expr_add) - expect(type_add?.toString()).toBe('long') - - const expr_sub = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_sub = services.typing.TypeComputer.inferType(expr_sub) - expect(type_sub?.toString()).toBe('long') - - const expr_mul = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_mul = services.typing.TypeComputer.inferType(expr_mul) - expect(type_mul?.toString()).toBe('long') - - const expr_div = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_div = services.typing.TypeComputer.inferType(expr_div) - expect(type_div?.toString()).toBe('long') - - const expr_mod = (script_long_zs.statements[10] as ExpressionStatement).expr - const type_mod = services.typing.TypeComputer.inferType(expr_mod) - expect(type_mod?.toString()).toBe('long') - // endregion - - // region Comparison - const expr_lt = (script_long_zs.statements[11] as ExpressionStatement).expr - const type_lt = services.typing.TypeComputer.inferType(expr_lt) - expect(type_lt?.toString()).toBe('bool') - - const expr_gt = (script_long_zs.statements[12] as ExpressionStatement).expr - const type_gt = services.typing.TypeComputer.inferType(expr_gt) - expect(type_gt?.toString()).toBe('bool') - - const expr_le = (script_long_zs.statements[13] as ExpressionStatement).expr - const type_le = services.typing.TypeComputer.inferType(expr_le) - expect(type_le?.toString()).toBe('bool') - - const expr_ge = (script_long_zs.statements[14] as ExpressionStatement).expr - const type_ge = services.typing.TypeComputer.inferType(expr_ge) - expect(type_ge?.toString()).toBe('bool') - - const expr_eq = (script_long_zs.statements[15] as ExpressionStatement).expr - const type_eq = services.typing.TypeComputer.inferType(expr_eq) - expect(type_eq?.toString()).toBe('bool') - - const expr_nq = (script_long_zs.statements[16] as ExpressionStatement).expr - const type_ne = services.typing.TypeComputer.inferType(expr_nq) - expect(type_ne?.toString()).toBe('bool') - // endregion + suite('binary', () => { + suite('arithmetic', () => { + it('&', () => { + const expr_and = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_and = services.typing.TypeComputer.inferType(expr_and) + expect(type_and?.toString()).toBe('long') + }) + + it('|', () => { + const expr_or = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_or = services.typing.TypeComputer.inferType(expr_or) + expect(type_or?.toString()).toBe('long') + }) + + it('^', () => { + const expr_xor = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_xor = services.typing.TypeComputer.inferType(expr_xor) + expect(type_xor?.toString()).toBe('long') + }) + + it('+', () => { + const expr_add = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_add = services.typing.TypeComputer.inferType(expr_add) + expect(type_add?.toString()).toBe('long') + }) + + it('-', () => { + const expr_sub = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_sub = services.typing.TypeComputer.inferType(expr_sub) + expect(type_sub?.toString()).toBe('long') + }) + + it('*', () => { + const expr_mul = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_mul = services.typing.TypeComputer.inferType(expr_mul) + expect(type_mul?.toString()).toBe('long') + }) + + it('/', () => { + const expr_div = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_div = services.typing.TypeComputer.inferType(expr_div) + expect(type_div?.toString()).toBe('long') + }) + + it('%', () => { + const expr_mod = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_mod = services.typing.TypeComputer.inferType(expr_mod) + expect(type_mod?.toString()).toBe('long') + }) + }) + + suite('comparison', () => { + it('<', () => { + const expr_lt = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_lt = services.typing.TypeComputer.inferType(expr_lt) + expect(type_lt?.toString()).toBe('bool') + }) + + it('>', () => { + const expr_gt = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_gt = services.typing.TypeComputer.inferType(expr_gt) + expect(type_gt?.toString()).toBe('bool') + }) + + it('<=', () => { + const expr_le = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_le = services.typing.TypeComputer.inferType(expr_le) + expect(type_le?.toString()).toBe('bool') + }) + + it('>=', () => { + const expr_ge = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_ge = services.typing.TypeComputer.inferType(expr_ge) + expect(type_ge?.toString()).toBe('bool') + }) + + it('==', () => { + const expr_eq = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_eq = services.typing.TypeComputer.inferType(expr_eq) + expect(type_eq?.toString()).toBe('bool') + }) + + it('!=', () => { + const expr_nq = (script_long_zs.statements[++line] as ExpressionStatement).expr + const type_ne = services.typing.TypeComputer.inferType(expr_nq) + expect(type_ne?.toString()).toBe('bool') + }) + }) }) }) @@ -342,60 +470,84 @@ describe(`check operation of float`, async () => { assertNoErrors(document_float_zs) }) - it('unary', () => { - const expr_neg = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_neg = services.typing.TypeComputer.inferType(expr_neg) - expect(type_neg?.toString()).toBe('float') + suite('unary', () => { + it('-', () => { + const expr_neg = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_neg = services.typing.TypeComputer.inferType(expr_neg) + expect(type_neg?.toString()).toBe('float') + }) }) - it('binary', () => { - // region Arithmetic - const expr_add = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_add = services.typing.TypeComputer.inferType(expr_add) - expect(type_add?.toString()).toBe('float') - - const expr_sub = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_sub = services.typing.TypeComputer.inferType(expr_sub) - expect(type_sub?.toString()).toBe('float') - - const expr_mul = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_mul = services.typing.TypeComputer.inferType(expr_mul) - expect(type_mul?.toString()).toBe('float') - - const expr_div = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_div = services.typing.TypeComputer.inferType(expr_div) - expect(type_div?.toString()).toBe('float') - - const expr_mod = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_mod = services.typing.TypeComputer.inferType(expr_mod) - expect(type_mod?.toString()).toBe('float') - // endregion - - // region Comparison - const expr_lt = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_lt = services.typing.TypeComputer.inferType(expr_lt) - expect(type_lt?.toString()).toBe('bool') - - const expr_gt = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_gt = services.typing.TypeComputer.inferType(expr_gt) - expect(type_gt?.toString()).toBe('bool') - - const expr_le = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_le = services.typing.TypeComputer.inferType(expr_le) - expect(type_le?.toString()).toBe('bool') - - const expr_ge = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_ge = services.typing.TypeComputer.inferType(expr_ge) - expect(type_ge?.toString()).toBe('bool') - - const expr_eq = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_eq = services.typing.TypeComputer.inferType(expr_eq) - expect(type_eq?.toString()).toBe('bool') - - const expr_nq = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_ne = services.typing.TypeComputer.inferType(expr_nq) - expect(type_ne?.toString()).toBe('bool') - // endregion + suite('binary', () => { + suite('arithmetic', () => { + it('+', () => { + const expr_add = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_add = services.typing.TypeComputer.inferType(expr_add) + expect(type_add?.toString()).toBe('float') + }) + + it('-', () => { + const expr_sub = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_sub = services.typing.TypeComputer.inferType(expr_sub) + expect(type_sub?.toString()).toBe('float') + }) + + it('*', () => { + const expr_mul = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_mul = services.typing.TypeComputer.inferType(expr_mul) + expect(type_mul?.toString()).toBe('float') + }) + + it('/', () => { + const expr_div = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_div = services.typing.TypeComputer.inferType(expr_div) + expect(type_div?.toString()).toBe('float') + }) + + it('%', () => { + const expr_mod = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_mod = services.typing.TypeComputer.inferType(expr_mod) + expect(type_mod?.toString()).toBe('float') + }) + }) + + suite('comparison', () => { + it('<', () => { + const expr_lt = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_lt = services.typing.TypeComputer.inferType(expr_lt) + expect(type_lt?.toString()).toBe('bool') + }) + + it('>', () => { + const expr_gt = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_gt = services.typing.TypeComputer.inferType(expr_gt) + expect(type_gt?.toString()).toBe('bool') + }) + + it('<=', () => { + const expr_le = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_le = services.typing.TypeComputer.inferType(expr_le) + expect(type_le?.toString()).toBe('bool') + }) + + it('>=', () => { + const expr_ge = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_ge = services.typing.TypeComputer.inferType(expr_ge) + expect(type_ge?.toString()).toBe('bool') + }) + + it('==', () => { + const expr_eq = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_eq = services.typing.TypeComputer.inferType(expr_eq) + expect(type_eq?.toString()).toBe('bool') + }) + + it('!=', () => { + const expr_nq = (script_float_zs.statements[++line] as ExpressionStatement).expr + const type_ne = services.typing.TypeComputer.inferType(expr_nq) + expect(type_ne?.toString()).toBe('bool') + }) + }) }) }) @@ -408,59 +560,83 @@ describe(`check operation of double`, async () => { assertNoErrors(document_double_zs) }) - it('unary', () => { - const expr_neg = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_neg = services.typing.TypeComputer.inferType(expr_neg) - expect(type_neg?.toString()).toBe('double') + suite('unary', () => { + it('-', () => { + const expr_neg = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_neg = services.typing.TypeComputer.inferType(expr_neg) + expect(type_neg?.toString()).toBe('double') + }) }) - it('binary', () => { - // region Arithmetic - const expr_add = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_add = services.typing.TypeComputer.inferType(expr_add) - expect(type_add?.toString()).toBe('double') - - const expr_sub = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_sub = services.typing.TypeComputer.inferType(expr_sub) - expect(type_sub?.toString()).toBe('double') - - const expr_mul = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_mul = services.typing.TypeComputer.inferType(expr_mul) - expect(type_mul?.toString()).toBe('double') - - const expr_div = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_div = services.typing.TypeComputer.inferType(expr_div) - expect(type_div?.toString()).toBe('double') - - const expr_mod = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_mod = services.typing.TypeComputer.inferType(expr_mod) - expect(type_mod?.toString()).toBe('double') - // endregion - - // region Comparison - const expr_lt = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_lt = services.typing.TypeComputer.inferType(expr_lt) - expect(type_lt?.toString()).toBe('bool') - - const expr_gt = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_gt = services.typing.TypeComputer.inferType(expr_gt) - expect(type_gt?.toString()).toBe('bool') - - const expr_le = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_le = services.typing.TypeComputer.inferType(expr_le) - expect(type_le?.toString()).toBe('bool') - - const expr_ge = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_ge = services.typing.TypeComputer.inferType(expr_ge) - expect(type_ge?.toString()).toBe('bool') - - const expr_eq = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_eq = services.typing.TypeComputer.inferType(expr_eq) - expect(type_eq?.toString()).toBe('bool') - - const expr_nq = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_ne = services.typing.TypeComputer.inferType(expr_nq) - expect(type_ne?.toString()).toBe('bool') - // endregion + suite('binary', () => { + suite('arithmetic', () => { + it('+', () => { + const expr_add = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_add = services.typing.TypeComputer.inferType(expr_add) + expect(type_add?.toString()).toBe('double') + }) + + it('-', () => { + const expr_sub = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_sub = services.typing.TypeComputer.inferType(expr_sub) + expect(type_sub?.toString()).toBe('double') + }) + + it('*', () => { + const expr_mul = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_mul = services.typing.TypeComputer.inferType(expr_mul) + expect(type_mul?.toString()).toBe('double') + }) + + it('/', () => { + const expr_div = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_div = services.typing.TypeComputer.inferType(expr_div) + expect(type_div?.toString()).toBe('double') + }) + + it('%', () => { + const expr_mod = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_mod = services.typing.TypeComputer.inferType(expr_mod) + expect(type_mod?.toString()).toBe('double') + }) + }) + + suite('comparison', () => { + it('<', () => { + const expr_lt = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_lt = services.typing.TypeComputer.inferType(expr_lt) + expect(type_lt?.toString()).toBe('bool') + }) + + it('>', () => { + const expr_gt = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_gt = services.typing.TypeComputer.inferType(expr_gt) + expect(type_gt?.toString()).toBe('bool') + }) + + it('<=', () => { + const expr_le = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_le = services.typing.TypeComputer.inferType(expr_le) + expect(type_le?.toString()).toBe('bool') + }) + + it('>=', () => { + const expr_ge = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_ge = services.typing.TypeComputer.inferType(expr_ge) + expect(type_ge?.toString()).toBe('bool') + }) + + it('==', () => { + const expr_eq = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_eq = services.typing.TypeComputer.inferType(expr_eq) + expect(type_eq?.toString()).toBe('bool') + }) + + it('!=', () => { + const expr_nq = (script_double_zs.statements[++line] as ExpressionStatement).expr + const type_ne = services.typing.TypeComputer.inferType(expr_nq) + expect(type_ne?.toString()).toBe('bool') + }) + }) }) }) From a8f33bf349e22efd54b808ed72ab414968cc10ef Mon Sep 17 00:00:00 2001 From: raylras Date: Tue, 26 Nov 2024 12:34:18 +0800 Subject: [PATCH 10/11] improve; more test --- packages/zenscript/src/builtins/bool.dzs | 2 +- packages/zenscript/src/builtins/string.dzs | 4 + .../zenscript/src/typing/type-computer.ts | 24 +- .../typing/operator/number-operation.test.ts | 642 --------------- .../test/typing/operator/operator.test.ts | 759 ++++++++++++++++++ .../test/typing/operator/scripts/array.zs | 7 + .../test/typing/operator/scripts/bool.zs | 10 + .../test/typing/operator/scripts/list.zs | 7 + .../test/typing/operator/scripts/map.zs | 7 + .../test/typing/operator/scripts/string.zs | 8 + 10 files changed, 813 insertions(+), 657 deletions(-) delete mode 100644 packages/zenscript/test/typing/operator/number-operation.test.ts create mode 100644 packages/zenscript/test/typing/operator/operator.test.ts create mode 100644 packages/zenscript/test/typing/operator/scripts/array.zs create mode 100644 packages/zenscript/test/typing/operator/scripts/bool.zs create mode 100644 packages/zenscript/test/typing/operator/scripts/list.zs create mode 100644 packages/zenscript/test/typing/operator/scripts/map.zs create mode 100644 packages/zenscript/test/typing/operator/scripts/string.zs diff --git a/packages/zenscript/src/builtins/bool.dzs b/packages/zenscript/src/builtins/bool.dzs index 01b2f4f7..79d0865c 100644 --- a/packages/zenscript/src/builtins/bool.dzs +++ b/packages/zenscript/src/builtins/bool.dzs @@ -8,5 +8,5 @@ zenClass bool { operator ==(value as bool) as bool; operator !=(value as bool) as bool; - operator as() as string + operator as() as string; } diff --git a/packages/zenscript/src/builtins/string.dzs b/packages/zenscript/src/builtins/string.dzs index 9a3818dc..1b77356f 100644 --- a/packages/zenscript/src/builtins/string.dzs +++ b/packages/zenscript/src/builtins/string.dzs @@ -91,5 +91,9 @@ zenClass string { operator [](index as int) as string; + operator ==(value as string) as bool; + + operator !=(value as string) as bool; + operator as() as bool, byte, int, short, long, float, double; } diff --git a/packages/zenscript/src/typing/type-computer.ts b/packages/zenscript/src/typing/type-computer.ts index 1997a726..56d0e85a 100644 --- a/packages/zenscript/src/typing/type-computer.ts +++ b/packages/zenscript/src/typing/type-computer.ts @@ -6,7 +6,7 @@ import type { BracketManager } from '../workspace/bracket-manager' import type { PackageManager } from '../workspace/package-manager' import type { BuiltinTypes, Type, TypeParameterSubstitutions } from './type-description' import { type AstNode, stream } from 'langium' -import { isAssignment, isCallExpression, isClassDeclaration, isExpression, isFunctionDeclaration, isFunctionExpression, isIndexingExpression, isOperatorFunctionDeclaration, isTypeParameter, isVariableDeclaration } from '../generated/ast' +import { isAssignment, isCallExpression, isClassDeclaration, isExpression, isFunctionDeclaration, isFunctionExpression, isOperatorFunctionDeclaration, isTypeParameter, isVariableDeclaration } from '../generated/ast' import { defineRules } from '../utils/rule' import { ClassType, CompoundType, FunctionType, IntersectionType, isAnyType, isClassType, isFunctionType, TypeVariable, UnionType } from './type-description' @@ -200,17 +200,8 @@ export class ZenScriptTypeComputer implements TypeComputer { // endregion // region Expression - Assignment: (source) => { - if (source.op === '=' && isIndexingExpression(source.left)) { - const operator = this.memberProvider().streamOperators(source.left.receiver) - .filter(it => it.op === '[]=') - .filter(it => it.parameters.length === 2) - .head() - return this.inferType(operator?.returnTypeRef) - } - else { - return this.inferType(source.right) - } + Assignment: () => { + return this.classTypeOf('void') }, ConditionalExpression: (source) => { @@ -328,12 +319,17 @@ export class ZenScriptTypeComputer implements TypeComputer { }, MemberAccess: (source) => { + const receiverType = this.inferType(source.receiver) + const targetContainer = source.target.ref?.$container if (isOperatorFunctionDeclaration(targetContainer) && targetContainer.op === '.') { - return this.inferType(targetContainer.returnTypeRef) + let dynamicTargetType = this.inferType(targetContainer.returnTypeRef) + if (dynamicTargetType && isClassType(receiverType)) { + dynamicTargetType = dynamicTargetType.substituteTypeParameters(receiverType.substitutions) + } + return dynamicTargetType } - const receiverType = this.inferType(source.receiver) let targetType = this.inferType(source.target.ref) if (targetType && isClassType(receiverType)) { targetType = targetType.substituteTypeParameters(receiverType.substitutions) diff --git a/packages/zenscript/test/typing/operator/number-operation.test.ts b/packages/zenscript/test/typing/operator/number-operation.test.ts deleted file mode 100644 index 0352517b..00000000 --- a/packages/zenscript/test/typing/operator/number-operation.test.ts +++ /dev/null @@ -1,642 +0,0 @@ -import type { ExpressionStatement } from '../../../src/generated/ast' -import path from 'node:path' -import { describe, expect, it, suite } from 'vitest' -import { assertNoErrors, createTestServices, getDocument } from '../../utils' - -const services = await createTestServices(__dirname) - -describe(`check operation of byte`, async () => { - const document_byte_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'byte.zs')) - const script_byte_zs = document_byte_zs.parseResult.value - let line = 0 - - it('syntax', () => { - assertNoErrors(document_byte_zs) - }) - - suite('unary', () => { - it('-', () => { - const expr_neg = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_neg = services.typing.TypeComputer.inferType(expr_neg) - expect(type_neg?.toString()).toBe('byte') - }) - - it('!', () => { - const expr_not = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_not = services.typing.TypeComputer.inferType(expr_not) - expect(type_not?.toString()).toBe('byte') - }) - }) - - suite('binary', () => { - suite('arithmetic', () => { - it('&', () => { - const expr_and = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_and = services.typing.TypeComputer.inferType(expr_and) - expect(type_and?.toString()).toBe('byte') - }) - - it('|', () => { - const expr_or = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_or = services.typing.TypeComputer.inferType(expr_or) - expect(type_or?.toString()).toBe('byte') - }) - - it('^', () => { - const expr_xor = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_xor = services.typing.TypeComputer.inferType(expr_xor) - expect(type_xor?.toString()).toBe('byte') - }) - - it('+', () => { - const expr_add = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_add = services.typing.TypeComputer.inferType(expr_add) - expect(type_add?.toString()).toBe('byte') - }) - - it('-', () => { - const expr_sub = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_sub = services.typing.TypeComputer.inferType(expr_sub) - expect(type_sub?.toString()).toBe('byte') - }) - - it('*', () => { - const expr_mul = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_mul = services.typing.TypeComputer.inferType(expr_mul) - expect(type_mul?.toString()).toBe('byte') - }) - - it('/', () => { - const expr_div = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_div = services.typing.TypeComputer.inferType(expr_div) - expect(type_div?.toString()).toBe('byte') - }) - - it('%', () => { - const expr_mod = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_mod = services.typing.TypeComputer.inferType(expr_mod) - expect(type_mod?.toString()).toBe('byte') - }) - }) - - suite('comparison', () => { - it('<', () => { - const expr_lt = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_lt = services.typing.TypeComputer.inferType(expr_lt) - expect(type_lt?.toString()).toBe('bool') - }) - - it('>', () => { - const expr_gt = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_gt = services.typing.TypeComputer.inferType(expr_gt) - expect(type_gt?.toString()).toBe('bool') - }) - - it('<=', () => { - const expr_le = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_le = services.typing.TypeComputer.inferType(expr_le) - expect(type_le?.toString()).toBe('bool') - }) - - it('>=', () => { - const expr_ge = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_ge = services.typing.TypeComputer.inferType(expr_ge) - expect(type_ge?.toString()).toBe('bool') - }) - - it('==', () => { - const expr_eq = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_eq = services.typing.TypeComputer.inferType(expr_eq) - expect(type_eq?.toString()).toBe('bool') - }) - - it('!=', () => { - const expr_nq = (script_byte_zs.statements[++line] as ExpressionStatement).expr - const type_ne = services.typing.TypeComputer.inferType(expr_nq) - expect(type_ne?.toString()).toBe('bool') - }) - }) - }) -}) - -describe(`check operation of short`, async () => { - const document_short_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'short.zs')) - const script_short_zs = document_short_zs.parseResult.value - let line = 0 - - it('syntax', () => { - assertNoErrors(document_short_zs) - }) - - suite('unary', () => { - it('-', () => { - const expr_neg = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_neg = services.typing.TypeComputer.inferType(expr_neg) - expect(type_neg?.toString()).toBe('short') - }) - - it('!', () => { - const expr_not = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_not = services.typing.TypeComputer.inferType(expr_not) - expect(type_not?.toString()).toBe('short') - }) - }) - - suite('binary', () => { - suite('arithmetic', () => { - it('&', () => { - const expr_and = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_and = services.typing.TypeComputer.inferType(expr_and) - expect(type_and?.toString()).toBe('short') - }) - - it('|', () => { - const expr_or = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_or = services.typing.TypeComputer.inferType(expr_or) - expect(type_or?.toString()).toBe('short') - }) - - it('^', () => { - const expr_xor = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_xor = services.typing.TypeComputer.inferType(expr_xor) - expect(type_xor?.toString()).toBe('short') - }) - - it('+', () => { - const expr_add = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_add = services.typing.TypeComputer.inferType(expr_add) - expect(type_add?.toString()).toBe('short') - }) - - it('-', () => { - const expr_sub = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_sub = services.typing.TypeComputer.inferType(expr_sub) - expect(type_sub?.toString()).toBe('short') - }) - - it('*', () => { - const expr_mul = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_mul = services.typing.TypeComputer.inferType(expr_mul) - expect(type_mul?.toString()).toBe('short') - }) - - it('/', () => { - const expr_div = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_div = services.typing.TypeComputer.inferType(expr_div) - expect(type_div?.toString()).toBe('short') - }) - - it('%', () => { - const expr_mod = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_mod = services.typing.TypeComputer.inferType(expr_mod) - expect(type_mod?.toString()).toBe('short') - }) - }) - - suite('comparison', () => { - it('<', () => { - const expr_lt = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_lt = services.typing.TypeComputer.inferType(expr_lt) - expect(type_lt?.toString()).toBe('bool') - }) - - it('>', () => { - const expr_gt = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_gt = services.typing.TypeComputer.inferType(expr_gt) - expect(type_gt?.toString()).toBe('bool') - }) - - it('<=', () => { - const expr_le = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_le = services.typing.TypeComputer.inferType(expr_le) - expect(type_le?.toString()).toBe('bool') - }) - - it('>=', () => { - const expr_ge = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_ge = services.typing.TypeComputer.inferType(expr_ge) - expect(type_ge?.toString()).toBe('bool') - }) - - it('==', () => { - const expr_eq = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_eq = services.typing.TypeComputer.inferType(expr_eq) - expect(type_eq?.toString()).toBe('bool') - }) - - it('!=', () => { - const expr_nq = (script_short_zs.statements[++line] as ExpressionStatement).expr - const type_ne = services.typing.TypeComputer.inferType(expr_nq) - expect(type_ne?.toString()).toBe('bool') - }) - }) - }) -}) - -describe(`check operation of int`, async () => { - const document_int_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'int.zs')) - const script_int_zs = document_int_zs.parseResult.value - let line = 0 - - it('syntax', () => { - assertNoErrors(document_int_zs) - }) - - suite('unary', () => { - it('-', () => { - const expr_neg = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_neg = services.typing.TypeComputer.inferType(expr_neg) - expect(type_neg?.toString()).toBe('int') - }) - - it('!', () => { - const expr_not = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_not = services.typing.TypeComputer.inferType(expr_not) - expect(type_not?.toString()).toBe('int') - }) - }) - - suite('binary', () => { - suite('arithmetic', () => { - it('&', () => { - const expr_and = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_and = services.typing.TypeComputer.inferType(expr_and) - expect(type_and?.toString()).toBe('int') - }) - - it('|', () => { - const expr_or = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_or = services.typing.TypeComputer.inferType(expr_or) - expect(type_or?.toString()).toBe('int') - }) - - it('^', () => { - const expr_xor = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_xor = services.typing.TypeComputer.inferType(expr_xor) - expect(type_xor?.toString()).toBe('int') - }) - - it('+', () => { - const expr_add = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_add = services.typing.TypeComputer.inferType(expr_add) - expect(type_add?.toString()).toBe('int') - }) - - it('-', () => { - const expr_sub = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_sub = services.typing.TypeComputer.inferType(expr_sub) - expect(type_sub?.toString()).toBe('int') - }) - - it('*', () => { - const expr_mul = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_mul = services.typing.TypeComputer.inferType(expr_mul) - expect(type_mul?.toString()).toBe('int') - }) - - it('/', () => { - const expr_div = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_div = services.typing.TypeComputer.inferType(expr_div) - expect(type_div?.toString()).toBe('int') - }) - - it('%', () => { - const expr_mod = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_mod = services.typing.TypeComputer.inferType(expr_mod) - expect(type_mod?.toString()).toBe('int') - }) - }) - - suite('comparison', () => { - it('<', () => { - const expr_lt = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_lt = services.typing.TypeComputer.inferType(expr_lt) - expect(type_lt?.toString()).toBe('bool') - }) - - it('>', () => { - const expr_gt = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_gt = services.typing.TypeComputer.inferType(expr_gt) - expect(type_gt?.toString()).toBe('bool') - }) - - it('<=', () => { - const expr_le = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_le = services.typing.TypeComputer.inferType(expr_le) - expect(type_le?.toString()).toBe('bool') - }) - - it('>=', () => { - const expr_ge = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_ge = services.typing.TypeComputer.inferType(expr_ge) - expect(type_ge?.toString()).toBe('bool') - }) - - it('==', () => { - const expr_eq = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_eq = services.typing.TypeComputer.inferType(expr_eq) - expect(type_eq?.toString()).toBe('bool') - }) - - it('!=', () => { - const expr_nq = (script_int_zs.statements[++line] as ExpressionStatement).expr - const type_ne = services.typing.TypeComputer.inferType(expr_nq) - expect(type_ne?.toString()).toBe('bool') - }) - }) - }) -}) - -describe(`check operation of long`, async () => { - const document_long_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'long.zs')) - const script_long_zs = document_long_zs.parseResult.value - let line = 0 - - it('syntax', () => { - assertNoErrors(document_long_zs) - }) - - suite('unary', () => { - it('-', () => { - const expr_neg = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_neg = services.typing.TypeComputer.inferType(expr_neg) - expect(type_neg?.toString()).toBe('long') - }) - - it('!', () => { - const expr_not = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_not = services.typing.TypeComputer.inferType(expr_not) - expect(type_not?.toString()).toBe('long') - }) - }) - - suite('binary', () => { - suite('arithmetic', () => { - it('&', () => { - const expr_and = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_and = services.typing.TypeComputer.inferType(expr_and) - expect(type_and?.toString()).toBe('long') - }) - - it('|', () => { - const expr_or = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_or = services.typing.TypeComputer.inferType(expr_or) - expect(type_or?.toString()).toBe('long') - }) - - it('^', () => { - const expr_xor = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_xor = services.typing.TypeComputer.inferType(expr_xor) - expect(type_xor?.toString()).toBe('long') - }) - - it('+', () => { - const expr_add = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_add = services.typing.TypeComputer.inferType(expr_add) - expect(type_add?.toString()).toBe('long') - }) - - it('-', () => { - const expr_sub = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_sub = services.typing.TypeComputer.inferType(expr_sub) - expect(type_sub?.toString()).toBe('long') - }) - - it('*', () => { - const expr_mul = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_mul = services.typing.TypeComputer.inferType(expr_mul) - expect(type_mul?.toString()).toBe('long') - }) - - it('/', () => { - const expr_div = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_div = services.typing.TypeComputer.inferType(expr_div) - expect(type_div?.toString()).toBe('long') - }) - - it('%', () => { - const expr_mod = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_mod = services.typing.TypeComputer.inferType(expr_mod) - expect(type_mod?.toString()).toBe('long') - }) - }) - - suite('comparison', () => { - it('<', () => { - const expr_lt = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_lt = services.typing.TypeComputer.inferType(expr_lt) - expect(type_lt?.toString()).toBe('bool') - }) - - it('>', () => { - const expr_gt = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_gt = services.typing.TypeComputer.inferType(expr_gt) - expect(type_gt?.toString()).toBe('bool') - }) - - it('<=', () => { - const expr_le = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_le = services.typing.TypeComputer.inferType(expr_le) - expect(type_le?.toString()).toBe('bool') - }) - - it('>=', () => { - const expr_ge = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_ge = services.typing.TypeComputer.inferType(expr_ge) - expect(type_ge?.toString()).toBe('bool') - }) - - it('==', () => { - const expr_eq = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_eq = services.typing.TypeComputer.inferType(expr_eq) - expect(type_eq?.toString()).toBe('bool') - }) - - it('!=', () => { - const expr_nq = (script_long_zs.statements[++line] as ExpressionStatement).expr - const type_ne = services.typing.TypeComputer.inferType(expr_nq) - expect(type_ne?.toString()).toBe('bool') - }) - }) - }) -}) - -describe(`check operation of float`, async () => { - const document_float_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'float.zs')) - const script_float_zs = document_float_zs.parseResult.value - let line = 0 - - it('syntax', () => { - assertNoErrors(document_float_zs) - }) - - suite('unary', () => { - it('-', () => { - const expr_neg = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_neg = services.typing.TypeComputer.inferType(expr_neg) - expect(type_neg?.toString()).toBe('float') - }) - }) - - suite('binary', () => { - suite('arithmetic', () => { - it('+', () => { - const expr_add = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_add = services.typing.TypeComputer.inferType(expr_add) - expect(type_add?.toString()).toBe('float') - }) - - it('-', () => { - const expr_sub = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_sub = services.typing.TypeComputer.inferType(expr_sub) - expect(type_sub?.toString()).toBe('float') - }) - - it('*', () => { - const expr_mul = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_mul = services.typing.TypeComputer.inferType(expr_mul) - expect(type_mul?.toString()).toBe('float') - }) - - it('/', () => { - const expr_div = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_div = services.typing.TypeComputer.inferType(expr_div) - expect(type_div?.toString()).toBe('float') - }) - - it('%', () => { - const expr_mod = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_mod = services.typing.TypeComputer.inferType(expr_mod) - expect(type_mod?.toString()).toBe('float') - }) - }) - - suite('comparison', () => { - it('<', () => { - const expr_lt = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_lt = services.typing.TypeComputer.inferType(expr_lt) - expect(type_lt?.toString()).toBe('bool') - }) - - it('>', () => { - const expr_gt = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_gt = services.typing.TypeComputer.inferType(expr_gt) - expect(type_gt?.toString()).toBe('bool') - }) - - it('<=', () => { - const expr_le = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_le = services.typing.TypeComputer.inferType(expr_le) - expect(type_le?.toString()).toBe('bool') - }) - - it('>=', () => { - const expr_ge = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_ge = services.typing.TypeComputer.inferType(expr_ge) - expect(type_ge?.toString()).toBe('bool') - }) - - it('==', () => { - const expr_eq = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_eq = services.typing.TypeComputer.inferType(expr_eq) - expect(type_eq?.toString()).toBe('bool') - }) - - it('!=', () => { - const expr_nq = (script_float_zs.statements[++line] as ExpressionStatement).expr - const type_ne = services.typing.TypeComputer.inferType(expr_nq) - expect(type_ne?.toString()).toBe('bool') - }) - }) - }) -}) - -describe(`check operation of double`, async () => { - const document_double_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'double.zs')) - const script_double_zs = document_double_zs.parseResult.value - let line = 0 - - it('syntax', () => { - assertNoErrors(document_double_zs) - }) - - suite('unary', () => { - it('-', () => { - const expr_neg = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_neg = services.typing.TypeComputer.inferType(expr_neg) - expect(type_neg?.toString()).toBe('double') - }) - }) - - suite('binary', () => { - suite('arithmetic', () => { - it('+', () => { - const expr_add = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_add = services.typing.TypeComputer.inferType(expr_add) - expect(type_add?.toString()).toBe('double') - }) - - it('-', () => { - const expr_sub = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_sub = services.typing.TypeComputer.inferType(expr_sub) - expect(type_sub?.toString()).toBe('double') - }) - - it('*', () => { - const expr_mul = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_mul = services.typing.TypeComputer.inferType(expr_mul) - expect(type_mul?.toString()).toBe('double') - }) - - it('/', () => { - const expr_div = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_div = services.typing.TypeComputer.inferType(expr_div) - expect(type_div?.toString()).toBe('double') - }) - - it('%', () => { - const expr_mod = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_mod = services.typing.TypeComputer.inferType(expr_mod) - expect(type_mod?.toString()).toBe('double') - }) - }) - - suite('comparison', () => { - it('<', () => { - const expr_lt = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_lt = services.typing.TypeComputer.inferType(expr_lt) - expect(type_lt?.toString()).toBe('bool') - }) - - it('>', () => { - const expr_gt = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_gt = services.typing.TypeComputer.inferType(expr_gt) - expect(type_gt?.toString()).toBe('bool') - }) - - it('<=', () => { - const expr_le = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_le = services.typing.TypeComputer.inferType(expr_le) - expect(type_le?.toString()).toBe('bool') - }) - - it('>=', () => { - const expr_ge = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_ge = services.typing.TypeComputer.inferType(expr_ge) - expect(type_ge?.toString()).toBe('bool') - }) - - it('==', () => { - const expr_eq = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_eq = services.typing.TypeComputer.inferType(expr_eq) - expect(type_eq?.toString()).toBe('bool') - }) - - it('!=', () => { - const expr_nq = (script_double_zs.statements[++line] as ExpressionStatement).expr - const type_ne = services.typing.TypeComputer.inferType(expr_nq) - expect(type_ne?.toString()).toBe('bool') - }) - }) - }) -}) diff --git a/packages/zenscript/test/typing/operator/operator.test.ts b/packages/zenscript/test/typing/operator/operator.test.ts new file mode 100644 index 00000000..e04d60a1 --- /dev/null +++ b/packages/zenscript/test/typing/operator/operator.test.ts @@ -0,0 +1,759 @@ +import type { ExpressionStatement } from '../../../src/generated/ast' +import path from 'node:path' +import { describe, expect, it, suite } from 'vitest' +import { assertNoErrors, createTestServices, getDocument } from '../../utils' + +const services = await createTestServices(__dirname) +const inferType = services.typing.TypeComputer.inferType.bind(services.typing.TypeComputer) + +describe('check operation of bool', async () => { + const document_bool_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'bool.zs')) + const script_bool_zs = document_bool_zs.parseResult.value + let line = 0 + const next = () => (script_bool_zs.statements[++line] as ExpressionStatement).expr + + it('syntax', () => { + assertNoErrors(document_bool_zs) + }) + + suite('logical', () => { + it('!', () => { + const type_not = inferType(next()) + expect(type_not?.toString()).toBe('bool') + }) + }) + + suite('bitwise', () => { + it('&', () => { + const type_and = inferType(next()) + expect(type_and?.toString()).toBe('bool') + }) + + it('|', () => { + const type_or = inferType(next()) + expect(type_or?.toString()).toBe('bool') + }) + + it('^', () => { + const type_xor = inferType(next()) + expect(type_xor?.toString()).toBe('bool') + }) + }) + + suite('comparison', () => { + it('==', () => { + const type_eq = inferType(next()) + expect(type_eq?.toString()).toBe('bool') + }) + + it('!=', () => { + const type_ne = inferType(next()) + expect(type_ne?.toString()).toBe('bool') + }) + }) +}) + +describe('check operation of string', async () => { + const document_string_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'string.zs')) + const script_string_zs = document_string_zs.parseResult.value + let line = 0 + const next = () => (script_string_zs.statements[++line] as ExpressionStatement).expr + + it('syntax', () => { + assertNoErrors(document_string_zs) + }) + + suite('binary', () => { + it('+', () => { + const type_has = inferType(next()) + expect(type_has?.toString()).toBe('string') + }) + + it('has', () => { + const type_has = inferType(next()) + expect(type_has?.toString()).toBe('bool') + }) + + it('[]', () => { + const type_index_get = inferType(next()) + expect(type_index_get?.toString()).toBe('string') + }) + + it('==', () => { + const type_eq = inferType(next()) + expect(type_eq?.toString()).toBe('bool') + }) + + it('!=', () => { + const type_ne = inferType(next()) + expect(type_ne?.toString()).toBe('bool') + }) + }) +}) + +describe(`check operation of byte`, async () => { + const document_byte_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'byte.zs')) + const script_byte_zs = document_byte_zs.parseResult.value + let line = 0 + const next = () => (script_byte_zs.statements[++line] as ExpressionStatement).expr + + it('syntax', () => { + assertNoErrors(document_byte_zs) + }) + + suite('unary', () => { + it('-', () => { + const type_neg = inferType(next()) + expect(type_neg?.toString()).toBe('byte') + }) + + it('!', () => { + const type_not = inferType(next()) + expect(type_not?.toString()).toBe('byte') + }) + }) + + suite('binary', () => { + suite('bitwise', () => { + it('&', () => { + const type_and = inferType(next()) + expect(type_and?.toString()).toBe('byte') + }) + + it('|', () => { + const type_or = inferType(next()) + expect(type_or?.toString()).toBe('byte') + }) + + it('^', () => { + const type_xor = inferType(next()) + expect(type_xor?.toString()).toBe('byte') + }) + }) + + suite('arithmetic', () => { + it('+', () => { + const type_add = inferType(next()) + expect(type_add?.toString()).toBe('byte') + }) + + it('-', () => { + const type_sub = inferType(next()) + expect(type_sub?.toString()).toBe('byte') + }) + + it('*', () => { + const type_mul = inferType(next()) + expect(type_mul?.toString()).toBe('byte') + }) + + it('/', () => { + const type_div = inferType(next()) + expect(type_div?.toString()).toBe('byte') + }) + + it('%', () => { + const type_mod = inferType(next()) + expect(type_mod?.toString()).toBe('byte') + }) + }) + + suite('comparison', () => { + it('<', () => { + const type_lt = inferType(next()) + expect(type_lt?.toString()).toBe('bool') + }) + + it('>', () => { + const type_gt = inferType(next()) + expect(type_gt?.toString()).toBe('bool') + }) + + it('<=', () => { + const type_le = inferType(next()) + expect(type_le?.toString()).toBe('bool') + }) + + it('>=', () => { + const type_ge = inferType(next()) + expect(type_ge?.toString()).toBe('bool') + }) + + it('==', () => { + const type_eq = inferType(next()) + expect(type_eq?.toString()).toBe('bool') + }) + + it('!=', () => { + const type_ne = inferType(next()) + expect(type_ne?.toString()).toBe('bool') + }) + }) + }) +}) + +describe(`check operation of short`, async () => { + const document_short_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'short.zs')) + const script_short_zs = document_short_zs.parseResult.value + let line = 0 + const next = () => (script_short_zs.statements[++line] as ExpressionStatement).expr + + it('syntax', () => { + assertNoErrors(document_short_zs) + }) + + suite('unary', () => { + it('-', () => { + const type_neg = inferType(next()) + expect(type_neg?.toString()).toBe('short') + }) + + it('!', () => { + const type_not = inferType(next()) + expect(type_not?.toString()).toBe('short') + }) + }) + + suite('binary', () => { + suite('bitwise', () => { + it('&', () => { + const type_and = inferType(next()) + expect(type_and?.toString()).toBe('short') + }) + + it('|', () => { + const type_or = inferType(next()) + expect(type_or?.toString()).toBe('short') + }) + + it('^', () => { + const type_xor = inferType(next()) + expect(type_xor?.toString()).toBe('short') + }) + }) + + suite('arithmetic', () => { + it('+', () => { + const type_add = inferType(next()) + expect(type_add?.toString()).toBe('short') + }) + + it('-', () => { + const type_sub = inferType(next()) + expect(type_sub?.toString()).toBe('short') + }) + + it('*', () => { + const type_mul = inferType(next()) + expect(type_mul?.toString()).toBe('short') + }) + + it('/', () => { + const type_div = inferType(next()) + expect(type_div?.toString()).toBe('short') + }) + + it('%', () => { + const type_mod = inferType(next()) + expect(type_mod?.toString()).toBe('short') + }) + }) + + suite('comparison', () => { + it('<', () => { + const type_lt = inferType(next()) + expect(type_lt?.toString()).toBe('bool') + }) + + it('>', () => { + const type_gt = inferType(next()) + expect(type_gt?.toString()).toBe('bool') + }) + + it('<=', () => { + const type_le = inferType(next()) + expect(type_le?.toString()).toBe('bool') + }) + + it('>=', () => { + const type_ge = inferType(next()) + expect(type_ge?.toString()).toBe('bool') + }) + + it('==', () => { + const type_eq = inferType(next()) + expect(type_eq?.toString()).toBe('bool') + }) + + it('!=', () => { + const type_ne = inferType(next()) + expect(type_ne?.toString()).toBe('bool') + }) + }) + }) +}) + +describe(`check operation of int`, async () => { + const document_int_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'int.zs')) + const script_int_zs = document_int_zs.parseResult.value + let line = 0 + const next = () => (script_int_zs.statements[++line] as ExpressionStatement).expr + + it('syntax', () => { + assertNoErrors(document_int_zs) + }) + + suite('unary', () => { + it('-', () => { + const type_neg = inferType(next()) + expect(type_neg?.toString()).toBe('int') + }) + + it('!', () => { + const type_not = inferType(next()) + expect(type_not?.toString()).toBe('int') + }) + }) + + suite('binary', () => { + suite('bitwise', () => { + it('&', () => { + const type_and = inferType(next()) + expect(type_and?.toString()).toBe('int') + }) + + it('|', () => { + const type_or = inferType(next()) + expect(type_or?.toString()).toBe('int') + }) + + it('^', () => { + const type_xor = inferType(next()) + expect(type_xor?.toString()).toBe('int') + }) + }) + + suite('arithmetic', () => { + it('+', () => { + const type_add = inferType(next()) + expect(type_add?.toString()).toBe('int') + }) + + it('-', () => { + const type_sub = inferType(next()) + expect(type_sub?.toString()).toBe('int') + }) + + it('*', () => { + const type_mul = inferType(next()) + expect(type_mul?.toString()).toBe('int') + }) + + it('/', () => { + const type_div = inferType(next()) + expect(type_div?.toString()).toBe('int') + }) + + it('%', () => { + const type_mod = inferType(next()) + expect(type_mod?.toString()).toBe('int') + }) + }) + + suite('comparison', () => { + it('<', () => { + const type_lt = inferType(next()) + expect(type_lt?.toString()).toBe('bool') + }) + + it('>', () => { + const type_gt = inferType(next()) + expect(type_gt?.toString()).toBe('bool') + }) + + it('<=', () => { + const type_le = inferType(next()) + expect(type_le?.toString()).toBe('bool') + }) + + it('>=', () => { + const type_ge = inferType(next()) + expect(type_ge?.toString()).toBe('bool') + }) + + it('==', () => { + const type_eq = inferType(next()) + expect(type_eq?.toString()).toBe('bool') + }) + + it('!=', () => { + const type_ne = inferType(next()) + expect(type_ne?.toString()).toBe('bool') + }) + }) + }) +}) + +describe(`check operation of long`, async () => { + const document_long_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'long.zs')) + const script_long_zs = document_long_zs.parseResult.value + let line = 0 + const next = () => (script_long_zs.statements[++line] as ExpressionStatement).expr + + it('syntax', () => { + assertNoErrors(document_long_zs) + }) + + suite('unary', () => { + it('-', () => { + const type_neg = inferType(next()) + expect(type_neg?.toString()).toBe('long') + }) + + it('!', () => { + const type_not = inferType(next()) + expect(type_not?.toString()).toBe('long') + }) + }) + + suite('binary', () => { + suite('bitwise', () => { + it('&', () => { + const type_and = inferType(next()) + expect(type_and?.toString()).toBe('long') + }) + + it('|', () => { + const type_or = inferType(next()) + expect(type_or?.toString()).toBe('long') + }) + + it('^', () => { + const type_xor = inferType(next()) + expect(type_xor?.toString()).toBe('long') + }) + }) + + suite('arithmetic', () => { + it('+', () => { + const type_add = inferType(next()) + expect(type_add?.toString()).toBe('long') + }) + + it('-', () => { + const type_sub = inferType(next()) + expect(type_sub?.toString()).toBe('long') + }) + + it('*', () => { + const type_mul = inferType(next()) + expect(type_mul?.toString()).toBe('long') + }) + + it('/', () => { + const type_div = inferType(next()) + expect(type_div?.toString()).toBe('long') + }) + + it('%', () => { + const type_mod = inferType(next()) + expect(type_mod?.toString()).toBe('long') + }) + }) + + suite('comparison', () => { + it('<', () => { + const type_lt = inferType(next()) + expect(type_lt?.toString()).toBe('bool') + }) + + it('>', () => { + const type_gt = inferType(next()) + expect(type_gt?.toString()).toBe('bool') + }) + + it('<=', () => { + const type_le = inferType(next()) + expect(type_le?.toString()).toBe('bool') + }) + + it('>=', () => { + const type_ge = inferType(next()) + expect(type_ge?.toString()).toBe('bool') + }) + + it('==', () => { + const type_eq = inferType(next()) + expect(type_eq?.toString()).toBe('bool') + }) + + it('!=', () => { + const type_ne = inferType(next()) + expect(type_ne?.toString()).toBe('bool') + }) + }) + }) +}) + +describe(`check operation of float`, async () => { + const document_float_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'float.zs')) + const script_float_zs = document_float_zs.parseResult.value + let line = 0 + const next = () => (script_float_zs.statements[++line] as ExpressionStatement).expr + + it('syntax', () => { + assertNoErrors(document_float_zs) + }) + + suite('unary', () => { + it('-', () => { + const type_neg = inferType(next()) + expect(type_neg?.toString()).toBe('float') + }) + }) + + suite('binary', () => { + suite('arithmetic', () => { + it('+', () => { + const type_add = inferType(next()) + expect(type_add?.toString()).toBe('float') + }) + + it('-', () => { + const type_sub = inferType(next()) + expect(type_sub?.toString()).toBe('float') + }) + + it('*', () => { + const type_mul = inferType(next()) + expect(type_mul?.toString()).toBe('float') + }) + + it('/', () => { + const type_div = inferType(next()) + expect(type_div?.toString()).toBe('float') + }) + + it('%', () => { + const type_mod = inferType(next()) + expect(type_mod?.toString()).toBe('float') + }) + }) + + suite('comparison', () => { + it('<', () => { + const type_lt = inferType(next()) + expect(type_lt?.toString()).toBe('bool') + }) + + it('>', () => { + const type_gt = inferType(next()) + expect(type_gt?.toString()).toBe('bool') + }) + + it('<=', () => { + const type_le = inferType(next()) + expect(type_le?.toString()).toBe('bool') + }) + + it('>=', () => { + const type_ge = inferType(next()) + expect(type_ge?.toString()).toBe('bool') + }) + + it('==', () => { + const type_eq = inferType(next()) + expect(type_eq?.toString()).toBe('bool') + }) + + it('!=', () => { + const type_ne = inferType(next()) + expect(type_ne?.toString()).toBe('bool') + }) + }) + }) +}) + +describe(`check operation of double`, async () => { + const document_double_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'double.zs')) + const script_double_zs = document_double_zs.parseResult.value + let line = 0 + const next = () => (script_double_zs.statements[++line] as ExpressionStatement).expr + + it('syntax', () => { + assertNoErrors(document_double_zs) + }) + + suite('unary', () => { + it('-', () => { + const type_neg = inferType(next()) + expect(type_neg?.toString()).toBe('double') + }) + }) + + suite('binary', () => { + suite('arithmetic', () => { + it('+', () => { + const type_add = inferType(next()) + expect(type_add?.toString()).toBe('double') + }) + + it('-', () => { + const type_sub = inferType(next()) + expect(type_sub?.toString()).toBe('double') + }) + + it('*', () => { + const type_mul = inferType(next()) + expect(type_mul?.toString()).toBe('double') + }) + + it('/', () => { + const type_div = inferType(next()) + expect(type_div?.toString()).toBe('double') + }) + + it('%', () => { + const type_mod = inferType(next()) + expect(type_mod?.toString()).toBe('double') + }) + }) + + suite('comparison', () => { + it('<', () => { + const type_lt = inferType(next()) + expect(type_lt?.toString()).toBe('bool') + }) + + it('>', () => { + const type_gt = inferType(next()) + expect(type_gt?.toString()).toBe('bool') + }) + + it('<=', () => { + const type_le = inferType(next()) + expect(type_le?.toString()).toBe('bool') + }) + + it('>=', () => { + const type_ge = inferType(next()) + expect(type_ge?.toString()).toBe('bool') + }) + + it('==', () => { + const type_eq = inferType(next()) + expect(type_eq?.toString()).toBe('bool') + }) + + it('!=', () => { + const type_ne = inferType(next()) + expect(type_ne?.toString()).toBe('bool') + }) + }) + }) +}) + +describe('check operation of array', async () => { + const document_array_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'array.zs')) + const script_array_zs = document_array_zs.parseResult.value + let line = 0 + const next = () => (script_array_zs.statements[++line] as ExpressionStatement).expr + + it('syntax', () => { + assertNoErrors(document_array_zs) + }) + + suite('binary', () => { + it('has', () => { + const type_has = inferType(next()) + expect(type_has?.toString()).toBe('bool') + }) + + it('[]', () => { + const type_index_get = inferType(next()) + expect(type_index_get?.toString()).toBe('long') + }) + + it('+=', () => { + const type_add = inferType(next()) + expect(type_add?.toString()).toBe('void') + }) + }) + + suite('ternary', () => { + it('[]=', () => { + const type_index_set = inferType(next()) + expect(type_index_set?.toString()).toBe('void') + }) + }) +}) + +describe('check operation of list', async () => { + const document_list_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'list.zs')) + const script_list_zs = document_list_zs.parseResult.value + let line = 0 + const next = () => (script_list_zs.statements[++line] as ExpressionStatement).expr + + it('syntax', () => { + assertNoErrors(document_list_zs) + }) + + suite('binary', () => { + it('has', () => { + const type_has = inferType(next()) + expect(type_has?.toString()).toBe('bool') + }) + + it('[]', () => { + const type_index_get = inferType(next()) + expect(type_index_get?.toString()).toBe('long') + }) + + it('+=', () => { + const type_add = inferType(next()) + expect(type_add?.toString()).toBe('void') + }) + }) + + suite('ternary', () => { + it('[]=', () => { + const type_index_set = inferType(next()) + expect(type_index_set?.toString()).toBe('void') + }) + }) +}) + +describe('check operation of map', async () => { + const document_map_zs = await getDocument(services, path.resolve(__dirname, 'scripts', 'map.zs')) + const script_map_zs = document_map_zs.parseResult.value + let line = 0 + const next = () => (script_map_zs.statements[++line] as ExpressionStatement).expr + + it('syntax', () => { + assertNoErrors(document_map_zs) + }) + + suite('binary', () => { + it('has', () => { + const type_has = inferType(next()) + expect(type_has?.toString()).toBe('bool') + }) + + it('[]', () => { + const type_index_get = inferType(next()) + expect(type_index_get?.toString()).toBe('long') + }) + + it('.', () => { + const type_add = inferType(next()) + expect(type_add?.toString()).toBe('long') + }) + }) + + suite('ternary', () => { + it('[]=', () => { + const type_index_set = inferType(next()) + expect(type_index_set?.toString()).toBe('void') + }) + }) +}) diff --git a/packages/zenscript/test/typing/operator/scripts/array.zs b/packages/zenscript/test/typing/operator/scripts/array.zs new file mode 100644 index 00000000..48cc5ed2 --- /dev/null +++ b/packages/zenscript/test/typing/operator/scripts/array.zs @@ -0,0 +1,7 @@ +val arr = [] as long[]; + +arr has 1; +arr[0]; +arr += 1; + +arr[0] = 1; diff --git a/packages/zenscript/test/typing/operator/scripts/bool.zs b/packages/zenscript/test/typing/operator/scripts/bool.zs new file mode 100644 index 00000000..88684410 --- /dev/null +++ b/packages/zenscript/test/typing/operator/scripts/bool.zs @@ -0,0 +1,10 @@ +val bol = true as bool; + +!bol; + +bol & bol; +bol | bol; +bol ^ bol; + +bol == bol; +bol != bol; diff --git a/packages/zenscript/test/typing/operator/scripts/list.zs b/packages/zenscript/test/typing/operator/scripts/list.zs new file mode 100644 index 00000000..2bddd9ba --- /dev/null +++ b/packages/zenscript/test/typing/operator/scripts/list.zs @@ -0,0 +1,7 @@ +val list = [] as [long]; + +list has 1; +list[0]; +list += 1; + +list[0] = 1; diff --git a/packages/zenscript/test/typing/operator/scripts/map.zs b/packages/zenscript/test/typing/operator/scripts/map.zs new file mode 100644 index 00000000..9c23053f --- /dev/null +++ b/packages/zenscript/test/typing/operator/scripts/map.zs @@ -0,0 +1,7 @@ +val map = {} as long[string]; + +map has "k"; +map["k"]; +map.k; + +map["k"] = 1L; diff --git a/packages/zenscript/test/typing/operator/scripts/string.zs b/packages/zenscript/test/typing/operator/scripts/string.zs new file mode 100644 index 00000000..3ca22a60 --- /dev/null +++ b/packages/zenscript/test/typing/operator/scripts/string.zs @@ -0,0 +1,8 @@ +val str = "str" as string; + +str + str; +str has str; +str[0]; + +str == str; +str != str; From 1e8ed6765cf5fe3d3441565684186a66d666e52c Mon Sep 17 00:00:00 2001 From: raylras Date: Tue, 26 Nov 2024 12:38:06 +0800 Subject: [PATCH 11/11] minor comment --- packages/zenscript/src/typing/type-computer.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/zenscript/src/typing/type-computer.ts b/packages/zenscript/src/typing/type-computer.ts index 56d0e85a..0e4d7f95 100644 --- a/packages/zenscript/src/typing/type-computer.ts +++ b/packages/zenscript/src/typing/type-computer.ts @@ -223,10 +223,10 @@ export class ZenScriptTypeComputer implements TypeComputer { InfixExpression: (source) => { switch (source.op) { - case '&': // Arithmetic + case '&': // Bitwise case '|': case '^': - case '+': + case '+': // Arithmetic case '-': case '*': case '/': @@ -260,11 +260,11 @@ export class ZenScriptTypeComputer implements TypeComputer { return this.inferType(operator?.returnTypeRef) } - case '&&': + case '&&': // Logical case '||': return this.classTypeOf('bool') - case '~': + case '~': // String Concat return this.classTypeOf('string') } },