Browse Source

Implement the new type system

Lucas de Souza 6 năm trước cách đây
mục cha
commit
e7adc7648a

+ 26 - 0
js/typeSystem/baseTypes.js

@@ -0,0 +1,26 @@
+class BaseType {
+  constructor(name, ord) {
+    this.name = name;
+    this.ord = ord;
+  }
+
+  get value () {
+    return this.name;
+  }
+
+  isCompatible (another) {
+    if(another instanceof BaseType) {
+      return this.name === another.name && this.ord === another.ord;
+    }
+    return false;
+  }
+}
+
+export const BaseTypes = Object.freeze({
+  INTEGER: new BaseType("int", 0),
+  REAL: new BaseType("real", 1),
+  STRING: new BaseType("string", 2),
+  BOOLEAN: new BaseType("bool", 3),
+  VOID: new BaseType("void", 4),
+  UNDEFINED: new BaseType('undefined', 5)
+})

+ 20 - 0
js/typeSystem/compoundType.js

@@ -0,0 +1,20 @@
+import { Type } from "./types";
+
+export class CompoundType extends Type {
+
+  constructor (type, dimensions) {
+    super(null);
+    this.innerType = type;
+    this.dimensions = dimensions;
+  }
+
+  isCompatible (another) {
+    if(another instanceof CompoundType){
+      if(this.dimensions !== another.dimensions) {
+        return false;
+      }
+      return this.innerType.isCompatible(another.innerType);
+    }
+    return false;
+  }
+}

+ 30 - 0
js/typeSystem/multiType.js

@@ -0,0 +1,30 @@
+import { Type } from "./types";
+
+export class MultiType extends Type {
+
+  constructor (...types) {
+    super(null);
+    this.types = types;
+  }
+
+  get value () {
+    return null;
+  }
+
+  get ord () {
+    return null;
+  }
+
+  isCompatible (another) {
+    if(another instanceof Type) {
+      for (let i = 0; i < this.types.length; i++) {
+        const t = this.types[i];
+        if (t.isCompatible(another)) {
+          return true;
+        }
+      }
+      return false;
+    }
+    return false;
+  }
+}

+ 37 - 0
js/typeSystem/parsers.js

@@ -0,0 +1,37 @@
+import { LanguageService } from "../services/languageService";
+import { BigNumber } from 'bignumber.js'
+
+export function toInt (str) {
+  return new BigNumber(str);
+}
+
+export function toString (str) {
+  let value = str.replace(/^"/, '');
+  value = value.replace(/"$/, '');
+  value = value.replace(/\\b/g, "\b");
+  value = value.replace(/\\t/g, "\t");
+  value = value.replace(/\\n/g, "\n");
+  value = value.replace(/\\r/g, "\r");
+  value = value.replace(/\\\"/g, "\"");
+  value = value.replace(/\\\'/g, "\'");
+  value = value.replace(/\\\\/g, "\\");
+  return value;
+}
+
+export function toReal (value) {
+  return new BigNumber(value);
+}
+
+export function toBool (str) {
+  const val = "'" + str + "'";
+  const lexer = LanguageService.getCurrentLexer();
+  const instance = new lexer(null);
+  if (instance.literalNames[lexer.RK_TRUE] === val) {
+    return true;
+  } else if (instance.literalNames[lexer.RK_FALSE] === val) {
+    return false;
+  } else {
+    // TODO: better error message
+    throw new Error(str + "not a valid boolean");
+  }
+}

+ 43 - 0
js/typeSystem/types.js

@@ -0,0 +1,43 @@
+import { BaseTypes } from './baseTypes';
+import { MultiType } from "./multiType";
+
+export class Type {
+
+  constructor(baseType) {
+    this.baseType = baseType;
+  }
+
+  get value () {
+    return this.baseType.value;
+  }
+
+  get ord () {
+    return this.baseType.ord;
+  }
+
+  isCompatible (another) {
+    if(another instanceof Type) {
+      return this.baseType.isCompatible(another.baseType);
+    }
+    return false;
+  }
+}
+
+
+const INTEGER = new Type(BaseTypes.INTEGER);
+const REAL = new Type(BaseTypes.REAL);
+const STRING = new Type(BaseTypes.STRING);
+const BOOLEAN = new Type(BaseTypes.BOOLEAN);
+const VOID = new Type(BaseTypes.VOID);
+const UNDEFINED = new Type(BaseTypes.UNDEFINED);
+const ALL = new MultiType(innerTypes.INTEGER, innerTypes.REAL, innerTypes.STRING, innerTypes.BOOLEAN);
+
+export const Types = Object.freeze({
+  INTEGER: INTEGER,
+  REAL: REAL,
+  STRING: STRING,
+  BOOLEAN: BOOLEAN,
+  VOID: VOID,
+  UNDEFINED: UNDEFINED,
+  ALL: ALL
+});