Skip to content

Commit

Permalink
feat: Adds literals and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
RomarQ committed Feb 4, 2022
1 parent 38e1a48 commit 0454016
Show file tree
Hide file tree
Showing 14 changed files with 1,321 additions and 103 deletions.
21 changes: 19 additions & 2 deletions src/core/blockchain_operations.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { LineInfo } from '../misc/utils';
import { ILiteral } from '../typings/literal';
import BlockchainOperations from './enums/blockchain_operations';
import BlockchainOperations from './enums/blockchain_operation';
import TypeAtom from './enums/type';
import { Expression } from './expression';

/**
Expand Down Expand Up @@ -47,5 +48,21 @@ export const GetTotalVotingPower = () => new Expression(BlockchainOperations.tot
/**
* @see https://tezos.gitlab.io/michelson-reference/#instr-VOTING_POWER
*/
export const GetVotingPower = (key_hash: ILiteral<'key_hash'>, line = new LineInfo()) =>
export const GetVotingPower = (key_hash: ILiteral<TypeAtom.key_hash>, line = new LineInfo()) =>
new Expression(BlockchainOperations.voting_power, `${key_hash}`, line);

const Operations = {
GetAmount,
GetBalance,
GetChain_id,
GetLevel,
GetTimestamp,
GetSelf,
GetSelfAddress,
GetSender,
GetSource,
GetTotalVotingPower,
GetVotingPower,
};

export default Operations;
File renamed without changes.
29 changes: 29 additions & 0 deletions src/core/enums/literal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export enum LiteralAtom {
record = 'record',
variant = 'variant',
chain_id_cst = 'chain_id_cst',
unit = 'unit',
nat = 'nat',
int = 'int',
mutez = 'mutez',
bool = 'bool',
bytes = 'bytes',
string = 'string',
address = 'address',
timestamp = 'timestamp',
bls12_381_fr = 'bls12_381_fr',
bls12_381_g1 = 'bls12_381_g1',
bls12_381_g2 = 'bls12_381_g2',
key = 'key',
key_hash = 'key_hash',
list = 'list',
set = 'set',
Some = 'Some',
None = 'None',
map = 'map',
big_map = 'big_map',
signature = 'signature',
tuple = 'tuple',
}

export default LiteralAtom;
5 changes: 0 additions & 5 deletions src/core/enums/prim.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
export enum SmartPyAtom {
bigmap = 'bigmap', // Is used to define the bigmap type
tuple = 'tuple', // Is used to define tuple types
}

export enum Prim {
// Type
unit = 'unit',
Expand Down
35 changes: 35 additions & 0 deletions src/core/enums/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
export enum TypeAtom {
record = 'record',
variant = 'variant',
chain_id = 'chain_id',
unit = 'unit',
nat = 'nat',
int = 'int',
mutez = 'mutez',
bool = 'bool',
bytes = 'bytes',
string = 'string',
address = 'address',
timestamp = 'timestamp',
bls12_381_fr = 'bls12_381_fr',
bls12_381_g1 = 'bls12_381_g1',
bls12_381_g2 = 'bls12_381_g2',
key = 'key',
key_hash = 'key_hash',
list = 'list',
set = 'set',
option = 'option',
map = 'map',
big_map = 'bigmap',
signature = 'signature',
operation = 'operation',
never = 'never',
tuple = 'tuple',
lambda = 'lambda',
ticket = 'ticket',
sapling_state = 'sapling_state',
contract = 'contract',
sapling_transaction = 'sapling_transaction',
}

export default TypeAtom;
166 changes: 116 additions & 50 deletions src/core/literal/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { IType } from '../../typings/type';
import type { ILiteral } from '../../typings/literal';

import { capitalizeBoolean, LineInfo } from '../../misc/utils';
import { capitalizeBoolean, LineInfo, parenthesis } from '../../misc/utils';
import {
TNat,
TString,
Expand All @@ -24,24 +24,29 @@ import {
TBls12_381_fr,
TBls12_381_g1,
TBls12_381_g2,
TSignature,
TSet,
} from '../type';
import { Prim } from '../enums/prim';
import { IExpression, IExpressionKind } from '../../typings/expression';
import { Layout } from '../enums/layout';
import LiteralAtom from '../enums/literal';
import TypeAtom from '../enums/type';

class Literal<T extends string> implements ILiteral<T> {
class Literal<T extends TypeAtom> implements ILiteral<T> {
_isExpression = true as const;
// Used for type checking
_type = null as unknown as T;

constructor(
public name: T,
public value: number | string | boolean | undefined,
private name: LiteralAtom,
private value: number | string | boolean | undefined,
public type: IType,
public line: LineInfo,
private line: LineInfo,
) {}

toString() {
if (typeof this.value === 'undefined') {
return `(${this.name})`;
return parenthesis(this.name);
}
return `(literal (${this.name} ${this.value}) ${this.line})`;
}
Expand All @@ -51,51 +56,78 @@ class Literal<T extends string> implements ILiteral<T> {
}
}

class LiteralExpression<T extends TypeAtom> implements ILiteral<T> {
_isExpression = true as const;
// Used for type checking
_type = null as unknown as T;
type = {} as unknown as IType;

constructor(private name: LiteralAtom, private values: IExpression[], private line: LineInfo) {}

toString() {
if (this.values.length === 0) {
return parenthesis(this.name);
}
return `(${this.name} ${this.values.join(' ')} ${this.line})`;
}
}

class ListLiteral<T> implements ILiteral<T> {
_isExpression = true as const;
_type: T;

constructor(public name: T, public items: IExpressionKind[], public type: IType, public line: LineInfo) {}
constructor(
private name: LiteralAtom,
private items: IExpressionKind[],
public type: IType,
private line: LineInfo,
) {
// Just for typing purposes
this._type = null as unknown as T;
}

toString() {
return `(${this.name} ${this.line} ${this.items.map((item) => item.toString()).join(' ')})`;
return `(${this.name} ${this.line} ${this.items.join(' ')})`;
}

toType() {
return this.type.toString();
}
}

class OptionLiteral implements ILiteral<'option'> {
class OptionLiteral implements ILiteral<TypeAtom.option> {
_isExpression = true as const;
name = 'option' as const;
_type = TypeAtom.option as const;

type: IType;

constructor(
public prim: Prim.Some | Prim.None,
public value: IExpressionKind | undefined,
public innerType: IType = TUnknown,
public line: LineInfo,
private prim: LiteralAtom.Some | LiteralAtom.None,
private value: IExpressionKind | undefined,
private innerType: IType = TUnknown,
private line: LineInfo,
) {
this.type = TOption(innerType);
}

toString(): string {
return `(variant "${this.prim}" ${this.value?.toString() || '(unit)'} ${this.line})`;
return `(${LiteralAtom.variant} "${this.prim}" ${this.value?.toString() || `(${LiteralAtom.unit})`} ${
this.line
})`;
}

toType() {
return this.type.toString();
}
}

class RecordLiteral implements ILiteral<'record'> {
class RecordLiteral implements ILiteral<TypeAtom.record> {
_isExpression = true as const;
name = 'record' as const;
_type = TypeAtom.record as const;

type: IType;

constructor(public fields: Record<string, ILiteral<unknown>>, public line: LineInfo) {
constructor(private fields: Record<string, ILiteral<unknown>>, private line: LineInfo) {
// Compute the record type (use rightcombs by default)
this.type = TRecord(
Object.entries(fields).reduce(
Expand All @@ -114,27 +146,34 @@ class RecordLiteral implements ILiteral<'record'> {
};

toString(): string {
return `(record ${this.line} ${this.buildFields(this.fields).join(' ')})`;
return `(${TypeAtom.record} ${this.line} ${this.buildFields(this.fields).join(' ')})`;
}

toType() {
return this.type.toString();
}
}

class MapLiteral<T extends Prim.map | Prim.big_map> implements ILiteral<T> {
class MapLiteral<T extends TypeAtom.map | TypeAtom.big_map> implements ILiteral<T> {
_isExpression = true as const;
name: T;
_type: T;

type: IType;

constructor(public prim: T, public rows: IExpression[][], keyType: IType, valueType: IType, public line: LineInfo) {
this.name = prim;
if (prim === Prim.map) {
constructor(
private prim: LiteralAtom.map | LiteralAtom.big_map,
private rows: IExpression[][],
keyType: IType,
valueType: IType,
private line: LineInfo,
) {
if (prim === LiteralAtom.map) {
this.type = TMap(keyType, valueType);
} else {
this.type = TBig_map(keyType, valueType);
}
// Just for typing purposes
this._type = null as unknown as T;
}

private buildEntry = ([key, value]: IExpression[]) => {
Expand All @@ -150,51 +189,66 @@ class MapLiteral<T extends Prim.map | Prim.big_map> implements ILiteral<T> {
}
}

export const Unit = () => new Literal(Prim.unit, undefined, TUnit(), new LineInfo());
export const Nat = (value: number) => new Literal(Prim.nat, value, TNat(), new LineInfo());
export const Int = (value: number) => new Literal(Prim.int, value, TInt(), new LineInfo());
export const Mutez = (value: number) => new Literal(Prim.mutez, value, TMutez(), new LineInfo());
export const String = (value: string) => new Literal(Prim.string, `"${value}"`, TString(), new LineInfo());
export const Bool = (value: boolean) => new Literal(Prim.bool, capitalizeBoolean(value), TBool(), new LineInfo());
export const Address = (address: string) => new Literal(Prim.address, address, TAddress(), new LineInfo());
export const Timestamp = (timestamp: number) => new Literal(Prim.timestamp, timestamp, TTimestamp(), new LineInfo());
export const Chain_id = (chainID: string) => new Literal('chain_id_cst', chainID, TChain_id(), new LineInfo());
export const Bytes = (bytes: string) => new Literal(Prim.bytes, bytes, TBytes(), new LineInfo());
export const Bls12_381_fr = (fr: string | number) =>
new Literal(Prim.bls12_381_fr, fr, TBls12_381_fr(), new LineInfo());
export const Bls12_381_g1 = (bytes: string) => new Literal(Prim.bls12_381_g1, bytes, TBls12_381_g1(), new LineInfo());
export const Bls12_381_g2 = (bytes: string) => new Literal(Prim.bls12_381_g2, bytes, TBls12_381_g2(), new LineInfo());
export const Key = (key: string) => new Literal(Prim.key, key, TKey(), new LineInfo());
export const Key_hash = (key_hash: string) => new Literal(Prim.key_hash, key_hash, TKey_hash(), new LineInfo());
export const Unit = (line = new LineInfo()) => new Literal<TypeAtom.unit>(LiteralAtom.unit, undefined, TUnit(), line);
export const Nat = (value: number, line = new LineInfo()) =>
new Literal<TypeAtom.nat>(LiteralAtom.nat, value, TNat(), line);
export const Int = (value: number, line = new LineInfo()) =>
new Literal<TypeAtom.int>(LiteralAtom.int, value, TInt(), line);
export const Mutez = (value: number, line = new LineInfo()) =>
new Literal<TypeAtom.mutez>(LiteralAtom.mutez, value, TMutez(), line);
export const String = (value: string, line = new LineInfo()) =>
new Literal<TypeAtom.string>(LiteralAtom.string, `"${value}"`, TString(), line);
export const Bool = (value: boolean, line = new LineInfo()) =>
new Literal<TypeAtom.bool>(LiteralAtom.bool, capitalizeBoolean(value), TBool(), line);
export const Address = (address: string, line = new LineInfo()) =>
new Literal<TypeAtom.address>(LiteralAtom.address, address, TAddress(), line);
export const Timestamp = (timestamp: number, line = new LineInfo()) =>
new Literal<TypeAtom.timestamp>(LiteralAtom.timestamp, timestamp, TTimestamp(), line);
export const Chain_id = (chainID: string, line = new LineInfo()) =>
new Literal<TypeAtom.chain_id>(LiteralAtom.chain_id_cst, chainID, TChain_id(), line);
export const Bytes = (bytes: string, line = new LineInfo()) =>
new Literal<TypeAtom.bytes>(LiteralAtom.bytes, bytes, TBytes(), line);
export const Bls12_381_fr = (fr: string | number, line = new LineInfo()) =>
new Literal<TypeAtom.bls12_381_fr>(LiteralAtom.bls12_381_fr, fr, TBls12_381_fr(), line);
export const Bls12_381_g1 = (bytes: string, line = new LineInfo()) =>
new Literal<TypeAtom.bls12_381_g1>(LiteralAtom.bls12_381_g1, bytes, TBls12_381_g1(), line);
export const Bls12_381_g2 = (bytes: string, line = new LineInfo()) =>
new Literal<TypeAtom.bls12_381_g2>(LiteralAtom.bls12_381_g2, bytes, TBls12_381_g2(), line);
export const Key = (key: string, line = new LineInfo()) =>
new Literal<TypeAtom.key>(LiteralAtom.key, key, TKey(), line);
export const Key_hash = (key_hash: string, line = new LineInfo()) =>
new Literal<TypeAtom.key_hash>(LiteralAtom.key_hash, key_hash, TKey_hash(), line);
export const Signature = (signature: string, line = new LineInfo()) =>
new Literal<TypeAtom.signature>(LiteralAtom.signature, signature, TSignature(), line);

// Containers
export const List = (items: IExpressionKind[], innerType: IType, line = new LineInfo()) =>
new ListLiteral(Prim.list, items, TList(innerType), line);
new ListLiteral<TypeAtom.list>(LiteralAtom.list, items, TList(innerType), line);
export const Set = (items: IExpressionKind[], innerType: IType, line = new LineInfo()) =>
new ListLiteral<TypeAtom.set>(LiteralAtom.set, items, TSet(innerType), line);
export const Some = (value: IExpressionKind, innerType?: IType, line = new LineInfo()) =>
new OptionLiteral(Prim.Some, value, innerType, line);
new OptionLiteral(LiteralAtom.Some, value, innerType, line);
export const None = (innerType?: IType, line = new LineInfo()) =>
new OptionLiteral(Prim.None, undefined, innerType, line);
new OptionLiteral(LiteralAtom.None, undefined, innerType, line);
export const Map = (
rows: IExpression[][] = [],
keyType: IType = TUnknown,
valueType: IType = TUnknown,
line = new LineInfo(),
) => new MapLiteral(Prim.map, rows, keyType, valueType, line);

) => new MapLiteral<TypeAtom.map>(LiteralAtom.map, rows, keyType, valueType, line);
export const Big_map = (
rows: IExpression[][] = [],
keyType: IType = TUnknown,
valueType: IType = TUnknown,
line = new LineInfo(),
) => new MapLiteral(Prim.big_map, rows, keyType, valueType, line);
) => new MapLiteral<TypeAtom.big_map>(LiteralAtom.big_map, rows, keyType, valueType, line);
export const Pair = (left: IExpression, right: IExpression, line = new LineInfo()) =>
new LiteralExpression<TypeAtom.tuple>(LiteralAtom.tuple, [left, right], line);

export const Record = (fields: Record<string, ILiteral<unknown>>, line = new LineInfo()) =>
new RecordLiteral(fields, line);

const Literals = {
Some,
None,
Record,
// Singletons
Unit,
Nat,
Expand All @@ -211,11 +265,23 @@ const Literals = {
Bls12_381_g2,
Key,
Key_hash,
Signature,
// Container types
List,
Set,
Some,
None,
Pair,
Map,
Big_map,
// Lambda,
// Ticket,
// Contract,
// Sapling_state,
// Sapling_transaction,
// Artificial Types
Record,
// Variant,
};

export default Literals;
Loading

0 comments on commit 0454016

Please sign in to comment.