mirror of
https://github.com/adelphes/android-dev-ext.git
synced 2025-12-23 09:59:25 +00:00
implement resolveExpression
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
/**
|
||||
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
|
||||
* @typedef {import('../body-types').ResolveInfo} ResolveInfo
|
||||
*/
|
||||
const { Expression } = require("./Expression");
|
||||
const { ArrayType } = require('java-mti');
|
||||
const { AnyType } = require('../anys');
|
||||
|
||||
class ArrayIndexExpression extends Expression {
|
||||
/**
|
||||
@@ -17,6 +20,17 @@ class ArrayIndexExpression extends Expression {
|
||||
tokens() {
|
||||
return [...this.instance.tokens, ...this.index.tokens];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolveInfo} ri
|
||||
*/
|
||||
resolveExpression(ri) {
|
||||
const instance_type = this.instance.resolveExpression(ri);
|
||||
if (instance_type instanceof ArrayType) {
|
||||
return instance_type.elementType;
|
||||
}
|
||||
return AnyType.Instance;
|
||||
}
|
||||
}
|
||||
|
||||
exports.ArrayIndexExpression = ArrayIndexExpression;
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
|
||||
* @typedef {import('../body-types').ResolveInfo} ResolveInfo
|
||||
* @typedef {import('../tokenizer').Token} Token
|
||||
*/
|
||||
const { Expression } = require("./Expression");
|
||||
const { ArrayValueType } = require('../anys');
|
||||
|
||||
class ArrayValueExpression extends Expression {
|
||||
/**
|
||||
@@ -18,6 +20,13 @@ class ArrayValueExpression extends Expression {
|
||||
tokens() {
|
||||
return this.open;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolveInfo} ri
|
||||
*/
|
||||
resolveExpression(ri) {
|
||||
return new ArrayValueType(this.elements.map(e => e.resolveExpression(ri)));
|
||||
}
|
||||
}
|
||||
|
||||
exports.ArrayValueExpression = ArrayValueExpression;
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
|
||||
* @typedef {import('../body-types').ResolveInfo} ResolveInfo
|
||||
* @typedef {import('../tokenizer').Token} Token
|
||||
*/
|
||||
const { Expression } = require("./Expression");
|
||||
const { JavaType, PrimitiveType } = require('java-mti');
|
||||
|
||||
class BinaryOpExpression extends Expression {
|
||||
/**
|
||||
@@ -17,6 +19,52 @@ class BinaryOpExpression extends Expression {
|
||||
this.rhs = rhs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolveInfo} ri
|
||||
*/
|
||||
resolveExpression(ri) {
|
||||
const operator = this.op.value;
|
||||
const lhstype = this.lhs.resolveExpression(ri);
|
||||
const rhstype = this.rhs.resolveExpression(ri);
|
||||
if (operator === '+') {
|
||||
const lhstypesig = lhstype instanceof JavaType && lhstype.typeSignature,
|
||||
rhstypesig = rhstype instanceof JavaType && rhstype.typeSignature;
|
||||
if (lhstypesig === 'Ljava/lang/String;') {
|
||||
return lhstype;
|
||||
}
|
||||
if (lhstypesig === 'D' || rhstypesig === 'D') {
|
||||
return PrimitiveType.map.D;
|
||||
}
|
||||
if (lhstypesig === 'F' || rhstypesig === 'F') {
|
||||
return PrimitiveType.map.F;
|
||||
}
|
||||
if (lhstypesig === 'J' || rhstypesig === 'J') {
|
||||
return PrimitiveType.map.J;
|
||||
}
|
||||
return PrimitiveType.map.I;
|
||||
}
|
||||
if (/^([*/%&|^+-]?=|<<=|>>>?=)$/.test(operator)) {
|
||||
// result of assignments are lhs
|
||||
return lhstype;
|
||||
}
|
||||
if (/^[*/%-]$/.test(operator)) {
|
||||
// math operators
|
||||
return PrimitiveType.map.I;
|
||||
}
|
||||
if (/^(<<|>>>?)$/.test(operator)) {
|
||||
// shift operators
|
||||
return PrimitiveType.map.I;
|
||||
}
|
||||
if (/^[&|^]$/.test(operator)) {
|
||||
// bitwise or logical operators
|
||||
return lhstype === PrimitiveType.map.Z ? lhstype : PrimitiveType.map.I;
|
||||
}
|
||||
if (operator === 'instanceof') {
|
||||
}
|
||||
// logical/comparison operators
|
||||
return PrimitiveType.map.Z;
|
||||
}
|
||||
|
||||
tokens() {
|
||||
return [...this.lhs.tokens, this.op, ...this.rhs.tokens];
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/**
|
||||
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
|
||||
* @typedef {import('../body-types').ResolveInfo} ResolveInfo
|
||||
*/
|
||||
const { Expression } = require("./Expression");
|
||||
|
||||
@@ -12,6 +13,13 @@ class BracketedExpression extends Expression {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolveInfo} ri
|
||||
*/
|
||||
resolveExpression(ri) {
|
||||
return this.expression.resolveExpression(ri);
|
||||
}
|
||||
|
||||
tokens() {
|
||||
return this.expression.tokens;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
/**
|
||||
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
|
||||
* @typedef {import('../body-types').ResolveInfo} ResolveInfo
|
||||
*/
|
||||
const { Expression } = require("./Expression");
|
||||
const { AnyType, TypeIdentType } = require('../anys');
|
||||
|
||||
class CastExpression extends Expression {
|
||||
/**
|
||||
@@ -14,6 +16,17 @@ class CastExpression extends Expression {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolveInfo} ri
|
||||
*/
|
||||
resolveExpression(ri) {
|
||||
const cast_type = this.castType.resolveExpression(ri);
|
||||
if (cast_type instanceof TypeIdentType) {
|
||||
return cast_type.type;
|
||||
}
|
||||
return AnyType.Instance;
|
||||
}
|
||||
|
||||
tokens() {
|
||||
return [...this.castType.tokens, ...this.expression.tokens];
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
|
||||
* @typedef {import('../tokenizer').Token} Token
|
||||
* @typedef {import('../body-types').ResolveInfo} ResolveInfo
|
||||
*/
|
||||
const { Expression } = require("./Expression");
|
||||
const { AnyType } = require('../anys');
|
||||
|
||||
class ClassMemberExpression extends Expression {
|
||||
/**
|
||||
@@ -15,6 +17,15 @@ class ClassMemberExpression extends Expression {
|
||||
this.classToken = class_token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolveInfo} ri
|
||||
*/
|
||||
resolveExpression(ri) {
|
||||
const classType = ri.typemap.get('java/lang/Class');
|
||||
const type = this.instance.types[0];
|
||||
return classType.specialise([type || AnyType.Instance]);
|
||||
}
|
||||
|
||||
tokens() {
|
||||
return this.classToken;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,21 @@
|
||||
/**
|
||||
* @typedef {import('java-mti').JavaType} JavaType
|
||||
* @typedef {import('java-mti').CEIType} CEIType
|
||||
* @typedef {import('../tokenizer').Token} Token
|
||||
*/
|
||||
* @typedef {import('../body-types').ResolveInfo} ResolveInfo
|
||||
* @typedef {import('../anys').ResolvedType} ResolvedType
|
||||
*/
|
||||
|
||||
class Expression {
|
||||
|
||||
/**
|
||||
* @param {ResolveInfo} ri
|
||||
* @returns {ResolvedType}
|
||||
*/
|
||||
resolveExpression(ri) {
|
||||
throw new Error('Expression.resolveType');
|
||||
}
|
||||
|
||||
/** @returns {Token|Token[]} */
|
||||
tokens() {
|
||||
throw new Error('Expression.tokens');
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
/**
|
||||
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
|
||||
* @typedef {import('../body-types').ResolveInfo} ResolveInfo
|
||||
* @typedef {import('../tokenizer').Token} Token
|
||||
*/
|
||||
const { Expression } = require("./Expression");
|
||||
const { PrimitiveType } = require('java-mti');
|
||||
const { AnyType } = require('../anys');
|
||||
|
||||
class IncDecExpression extends Expression {
|
||||
/**
|
||||
@@ -17,6 +20,19 @@ class IncDecExpression extends Expression {
|
||||
this.which = which;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolveInfo} ri
|
||||
*/
|
||||
resolveExpression(ri) {
|
||||
const type = this.expr.resolveExpression(ri);
|
||||
if (type instanceof PrimitiveType) {
|
||||
if (/^[BSIJFD]$/.test(type.typeSignature)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return AnyType.Instance;
|
||||
}
|
||||
|
||||
tokens() {
|
||||
return this.operator;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
|
||||
* @typedef {import('../body-types').ResolveInfo} ResolveInfo
|
||||
*/
|
||||
const { Expression } = require("./Expression");
|
||||
const { Block } = require('../statementtypes/Block');
|
||||
const { LambdaType } = require('../anys');
|
||||
|
||||
class LambdaExpression extends Expression {
|
||||
/**
|
||||
@@ -16,6 +18,13 @@ class LambdaExpression extends Expression {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolveInfo} ri
|
||||
*/
|
||||
resolveType(ri) {
|
||||
return new LambdaType();
|
||||
}
|
||||
|
||||
tokens() {
|
||||
if (this.body instanceof Block) {
|
||||
return this.body.open;
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
/**
|
||||
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
|
||||
* @typedef {import('../body-types').ResolveInfo} ResolveInfo
|
||||
* @typedef {import('../tokenizer').Token} Token
|
||||
*/
|
||||
const { Expression } = require("./Expression");
|
||||
const { CEIType } = require('java-mti');
|
||||
const { AnyType, MethodType } = require('../anys');
|
||||
const { getTypeInheritanceList } = require('../expression-resolver');
|
||||
|
||||
class MemberExpression extends Expression {
|
||||
/**
|
||||
@@ -16,6 +20,34 @@ class MemberExpression extends Expression {
|
||||
this.member = member;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolveInfo} ri
|
||||
*/
|
||||
resolveExpression(ri) {
|
||||
const type = this.instance.resolveExpression(ri);
|
||||
if (!(type instanceof CEIType)) {
|
||||
return AnyType.Instance;
|
||||
}
|
||||
const ident = this.member.value;
|
||||
const field = type.fields.find(f => f.name === ident);
|
||||
if (field) {
|
||||
return field.type;
|
||||
}
|
||||
let methods = new Map();
|
||||
getTypeInheritanceList(type).forEach(type => {
|
||||
type.methods.forEach(m => {
|
||||
let msig;
|
||||
if (m.name === ident && !methods.has(msig = m.methodSignature)) {
|
||||
methods.set(msig, m);
|
||||
}
|
||||
})
|
||||
});
|
||||
if (methods.size > 0) {
|
||||
return new MethodType([...methods.values()]);
|
||||
}
|
||||
return AnyType.Instance;
|
||||
}
|
||||
|
||||
tokens() {
|
||||
return this.member;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
/**
|
||||
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
|
||||
* @typedef {import('../body-types').ResolveInfo} ResolveInfo
|
||||
*/
|
||||
const { Expression } = require("./Expression");
|
||||
const { AnyType, MethodType } = require('../anys');
|
||||
|
||||
class MethodCallExpression extends Expression {
|
||||
/**
|
||||
@@ -14,6 +16,18 @@ class MethodCallExpression extends Expression {
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolveInfo} ri
|
||||
*/
|
||||
resolveExpression(ri) {
|
||||
const type = this.instance.resolveExpression(ri);
|
||||
if (!(type instanceof MethodType)) {
|
||||
return AnyType.Instance;
|
||||
}
|
||||
const arg_types = this.args.map(arg => arg.resolveExpression(ri));
|
||||
return type.methods[0].returnType;
|
||||
}
|
||||
|
||||
tokens() {
|
||||
return this.instance.tokens;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
/**
|
||||
* @typedef {import('../tokenizer').Token} Token
|
||||
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
|
||||
* @typedef {import('../body-types').ResolveInfo} ResolveInfo
|
||||
* @typedef {import('../source-types').SourceTypeIdent} SourceTypeIdent
|
||||
* @typedef {import('java-mti').JavaType} JavaType
|
||||
*/
|
||||
const { Expression } = require("./Expression");
|
||||
const { ArrayType } = require('java-mti');
|
||||
|
||||
class NewArray extends Expression {
|
||||
/**
|
||||
@@ -17,6 +19,14 @@ class NewArray extends Expression {
|
||||
this.new_token = new_token;
|
||||
this.element_type = element_type;
|
||||
this.dimensions = dimensions;
|
||||
this.array_type = new ArrayType(element_type.resolved, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolveInfo} ri
|
||||
*/
|
||||
resolveExpression(ri) {
|
||||
return this.array_type;
|
||||
}
|
||||
|
||||
tokens() {
|
||||
@@ -39,6 +49,13 @@ class NewObject extends Expression {
|
||||
this.type_body = type_body;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolveInfo} ri
|
||||
*/
|
||||
resolveExpression(ri) {
|
||||
return this.object_type.resolved;
|
||||
}
|
||||
|
||||
tokens() {
|
||||
return [this.new_token, ...this.object_type.tokens];
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
/**
|
||||
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
|
||||
*/
|
||||
* @typedef {import('../body-types').ResolveInfo} ResolveInfo
|
||||
*/
|
||||
const { Expression } = require("./Expression");
|
||||
const { MultiValueType } = require('../anys');
|
||||
|
||||
class TernaryOpExpression extends Expression {
|
||||
/**
|
||||
@@ -16,6 +18,15 @@ class TernaryOpExpression extends Expression {
|
||||
this.falseExpression = falseExpression;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolveInfo} ri
|
||||
*/
|
||||
resolveExpression(ri) {
|
||||
const ttype = this.truthExpression.resolveExpression(ri);
|
||||
const ftype = this.falseExpression.resolveExpression(ri);
|
||||
return new MultiValueType(ttype, ftype);
|
||||
}
|
||||
|
||||
tokens() {
|
||||
return [...this.test.tokens, ...this.truthExpression.tokens, ...this.falseExpression.tokens];
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
|
||||
* @typedef {import('../body-types').ResolveInfo} ResolveInfo
|
||||
* @typedef {import('../tokenizer').Token} Token
|
||||
*/
|
||||
const { Expression } = require("./Expression");
|
||||
const { AnyType, TypeIdentType } = require('../anys');
|
||||
|
||||
class ThisMemberExpression extends Expression {
|
||||
/**
|
||||
@@ -15,6 +17,18 @@ class ThisMemberExpression extends Expression {
|
||||
this.thisToken = this_token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolveInfo} ri
|
||||
*/
|
||||
resolveExpression(ri) {
|
||||
// instance should be a type identifier
|
||||
const typeident = this.instance.resolveExpression(ri);
|
||||
if (typeident instanceof TypeIdentType) {
|
||||
return typeident.type;
|
||||
}
|
||||
return AnyType.Instance;
|
||||
}
|
||||
|
||||
tokens() {
|
||||
return this.thisToken;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/**
|
||||
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
|
||||
* @typedef {import('../body-types').Local} Local
|
||||
* @typedef {import('../body-types').ResolveInfo} ResolveInfo
|
||||
* @typedef {import('../tokenizer').Token} Token
|
||||
* @typedef {import('java-mti').Field} Field
|
||||
* @typedef {import('java-mti').Parameter} Parameter
|
||||
@@ -20,6 +21,13 @@ class Variable extends Expression {
|
||||
this.type = this.variable.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolveInfo} ri
|
||||
*/
|
||||
resolveType(ri) {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
tokens() {
|
||||
return this.name_token;
|
||||
}
|
||||
|
||||
@@ -10,8 +10,7 @@ class BooleanLiteral extends LiteralValue {
|
||||
* @param {Token} token
|
||||
*/
|
||||
constructor(token) {
|
||||
super(token);
|
||||
this.type = PrimitiveType.map.Z;
|
||||
super(token, PrimitiveType.map.Z);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,7 @@ class CharacterLiteral extends LiteralValue {
|
||||
* @param {Token} token
|
||||
*/
|
||||
constructor(token) {
|
||||
super(token);
|
||||
this.type = PrimitiveType.map.C;
|
||||
super(token, PrimitiveType.map.C);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/**
|
||||
* @typedef {import('../../body-types').ResolveInfo} ResolveInfo
|
||||
* @typedef {import('../../tokenizer').Token} Token
|
||||
* @typedef {import('java-mti').CEIType} CEIType
|
||||
*/
|
||||
@@ -11,9 +12,19 @@ class InstanceLiteral extends LiteralValue {
|
||||
* @param {CEIType} scoped_type
|
||||
*/
|
||||
constructor(token, scoped_type) {
|
||||
super(token);
|
||||
super(token, null);
|
||||
this.scoped_type = scoped_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolveInfo} ri
|
||||
*/
|
||||
resolveExpression(ri) {
|
||||
if (this.token.value === 'this') {
|
||||
return this.scoped_type;
|
||||
}
|
||||
return this.scoped_type.supers.find(t => t.typeKind === 'class') || ri.typemap.get('java/lang/Object');
|
||||
}
|
||||
}
|
||||
|
||||
exports.InstanceLiteral = InstanceLiteral;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
/**
|
||||
* @typedef {import('java-mti').JavaType} JavaType
|
||||
* @typedef {import('../../body-types').ResolveInfo} ResolveInfo
|
||||
* @typedef {import('../../tokenizer').Token} Token
|
||||
*/
|
||||
const { Expression } = require('../Expression');
|
||||
@@ -6,10 +8,19 @@ const { Expression } = require('../Expression');
|
||||
class LiteralValue extends Expression {
|
||||
/**
|
||||
* @param {Token} token
|
||||
* @param {JavaType} known_type
|
||||
*/
|
||||
constructor(token) {
|
||||
constructor(token, known_type) {
|
||||
super();
|
||||
this.token = token;
|
||||
this.type = known_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResolveInfo} ri
|
||||
*/
|
||||
resolveExpression(ri) {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
tokens() {
|
||||
|
||||
@@ -10,8 +10,7 @@ class NullLiteral extends LiteralValue {
|
||||
* @param {Token} token
|
||||
*/
|
||||
constructor(token) {
|
||||
super(token);
|
||||
this.type = new NullType();
|
||||
super(token, new NullType());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,9 +18,8 @@ class NumberLiteral extends LiteralValue {
|
||||
* @param {PrimitiveType} default_type
|
||||
*/
|
||||
constructor(value, kind, default_type) {
|
||||
super(value);
|
||||
super(value, default_type);
|
||||
this.numberKind = kind;
|
||||
this.type = default_type;
|
||||
}
|
||||
|
||||
static shift(a, b, op) {
|
||||
|
||||
@@ -11,8 +11,7 @@ class StringLiteral extends LiteralValue {
|
||||
* @param {CEIType} string_type
|
||||
*/
|
||||
constructor(token, string_type) {
|
||||
super(token);
|
||||
this.type = string_type;
|
||||
super(token, string_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user