Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion spell/cspell-list.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ Hoppity
idict
Ikko
Ilya
implicits
infixl
infixr
initof
Expand All @@ -97,8 +98,8 @@ Lagus
Laika
langle
langtools
letrec
learnXinYminutes
letrec
Liskov
llm
llms
Expand Down Expand Up @@ -166,6 +167,7 @@ seti
shardchains
shiki
Shvetc
Signedness
skywardboundd
Stateinit
statinit
Expand Down
4 changes: 2 additions & 2 deletions src/cli/colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ export const isColorSupported = () => {
if (process.platform === "win32") {
const [major, _, build] = release().split(".").map(Number);
// Windows 10, Build 10586+
return (
(major && major > 10) || (major === 10 && build && build >= 10586)
return Boolean(
(major && major > 10) || (major === 10 && build && build >= 10586),
);
}
if (process.stdout.isTTY && process.env.TERM !== "dumb") {
Expand Down
9 changes: 7 additions & 2 deletions src/error/logger-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,15 @@ const mapBaseLogger = <M1, M2, R>(
},
});

/**
* `SourceLogger` or top-level `Logger`
*/
export interface AnyLogger<M, R> extends Formatter<M>, BaseLogger<M, R> {}

/**
* Logger that knows about currently compiled file
*/
export interface SourceLogger<M, R> extends Formatter<M>, BaseLogger<M, R> {
export interface SourceLogger<M, R> extends AnyLogger<M, R> {
/**
* Choose range where an error will be shown
*/
Expand All @@ -110,7 +115,7 @@ export interface SourceLogger<M, R> extends Formatter<M>, BaseLogger<M, R> {
/**
* Top-level logger
*/
export interface Logger<M, R> extends Formatter<M>, BaseLogger<M, R> {
export interface Logger<M, R> extends AnyLogger<M, R> {
/**
* Set currently compiled source in logging context
*/
Expand Down
8 changes: 0 additions & 8 deletions src/imports/path.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { throwInternalCompilerError } from "@/error/errors";
import { repeat } from "@/utils/array";

// Witness tag. Do not use, do not export.
const pathTag = Symbol("path");

/**
* Safe relative path
*/
Expand All @@ -16,10 +13,6 @@ export type RelativePath = {
* /-separated strings that go after optional ../
*/
readonly segments: readonly string[];
/**
* Proof that path was created by RelativePath constructor
*/
readonly [pathTag]: true;
};

/**
Expand All @@ -33,7 +26,6 @@ const RelativePath = (
throwInternalCompilerError("Negative number of ../ in path");
}
const result: RelativePath = {
[pathTag]: true,
stepsUp,
segments: Object.freeze(segments),
};
Expand Down
31 changes: 31 additions & 0 deletions src/next/ast/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export type Range = {
readonly start: number;
readonly end: number;
};

export type OptionalId = Id | Wildcard;

export type Id = {
readonly kind: "id";
readonly text: string;
readonly loc: Range;
};

export type Wildcard = {
readonly kind: "wildcard";
readonly loc: Range;
};

export type FuncId = {
readonly kind: "func_id";
readonly text: string;
readonly loc: Range;
};

export type TypeId = {
readonly kind: "type_id";
readonly text: string;
readonly loc: Range;
};

export type Language = "func" | "tact";
193 changes: 193 additions & 0 deletions src/next/ast/expression.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
import type { Id, Range, TypeId } from "@/next/ast/common";
import type { Type, TypeMap } from "@/next/ast/type";

export type Expression =
| OpBinary
| OpUnary
| Conditional
| MethodCall
| FieldAccess
| StaticCall
| StructInstance
| InitOf
| CodeOf
| Number
| Boolean
| Null
| String
| Var
| Unit
| Tuple
| Tensor
| MapLiteral
| SetLiteral;

export type Var = {
readonly kind: "var";
readonly name: string;
readonly loc: Range;
};

export type Number = {
readonly kind: "number";
readonly base: NumberBase;
readonly value: bigint;
readonly loc: Range;
};

export type NumberBase = "2" | "8" | "10" | "16";

export type Boolean = {
readonly kind: "boolean";
readonly value: boolean;
readonly loc: Range;
};

// A String is a string in which escaping characters, like '\\' has been simplified, e.g., '\\' simplified to '\'.
export type String = {
readonly kind: "string";
readonly value: string;
readonly loc: Range;
};

// `null` value is an inhabitant of several types:
// it can represent missing values in optional types,
// or empty map of any key and value types
export type Null = {
readonly kind: "null";
readonly loc: Range;
};

export type BinaryOperation =
| "+"
| "-"
| "*"
| "/"
| "!="
| ">"
| "<"
| ">="
| "<="
| "=="
| "&&"
| "||"
| "%"
| "<<"
| ">>"
| "&"
| "|"
| "^";

export type OpBinary = {
readonly kind: "op_binary";
readonly op: BinaryOperation;
readonly left: Expression;
readonly right: Expression;
readonly loc: Range;
};

export type UnaryOperation = "+" | "-" | "!" | "!!" | "~";

export type OpUnary = {
readonly kind: "op_unary";
readonly op: UnaryOperation;
readonly operand: Expression;
readonly loc: Range;
};

export type FieldAccess = {
readonly kind: "field_access";
readonly aggregate: Expression; // contract, trait, struct, message
readonly field: Id;
readonly loc: Range;
};

export type MethodCall = {
readonly kind: "method_call";
readonly self: Expression; // anything with a method
readonly method: Id;
readonly typeArgs: readonly Type[];
readonly args: readonly Expression[];
readonly loc: Range;
};

// builtins or top-level (module) functions
export type StaticCall = {
readonly kind: "static_call";
readonly function: Id;
readonly typeArgs: readonly Type[];
readonly args: readonly Expression[];
readonly loc: Range;
};

export type StructInstance = {
readonly kind: "struct_instance";
readonly type: TypeId;
readonly typeArgs: readonly Type[];
readonly args: readonly StructFieldInitializer[];
readonly loc: Range;
};

export type StructFieldInitializer = {
readonly kind: "struct_field_initializer";
readonly field: Id;
readonly initializer: Expression;
readonly loc: Range;
};

export type MapLiteral = {
readonly kind: "map_literal";
readonly type: TypeMap;
readonly fields: readonly MapField[];
readonly loc: Range;
};

export type MapField = {
readonly key: Expression;
readonly value: Expression;
};

export type SetLiteral = {
readonly kind: "set_literal";
readonly valueType: Type;
readonly fields: readonly Expression[];
readonly loc: Range;
};

export type InitOf = {
readonly kind: "init_of";
readonly contract: TypeId;
readonly args: readonly Expression[];
readonly loc: Range;
};

export type CodeOf = {
readonly kind: "code_of";
readonly contract: TypeId;
readonly loc: Range;
};

export type Conditional = {
readonly kind: "conditional";
readonly condition: Expression;
readonly thenBranch: Expression;
readonly elseBranch: Expression;
readonly loc: Range;
};

export type Unit = {
readonly kind: "unit";
readonly loc: Range;
};

export type Tuple = {
readonly kind: "tuple";
readonly children: readonly Expression[];
readonly loc: Range;
};

export type Tensor = {
readonly kind: "tensor";
readonly children: readonly Expression[];
readonly loc: Range;
};
40 changes: 40 additions & 0 deletions src/next/ast/generated/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
import type * as $ from "@/next/ast/common";
export type Range = $.Range;
export const Range = (start: number, end: number): $.Range =>
Object.freeze({
start,
end,
});
export type Id = $.Id;
export const Id = (text: string, loc: $.Range): $.Id =>
Object.freeze({
kind: "id",
text,
loc,
});
export const isId = ($value: Id) => $value.kind === "id";
export type Wildcard = $.Wildcard;
export const Wildcard = (loc: $.Range): $.Wildcard =>
Object.freeze({
kind: "wildcard",
loc,
});
export const isWildcard = ($value: Wildcard) => $value.kind === "wildcard";
export type OptionalId = $.OptionalId;
export type FuncId = $.FuncId;
export const FuncId = (text: string, loc: $.Range): $.FuncId =>
Object.freeze({
kind: "func_id",
text,
loc,
});
export const isFuncId = ($value: FuncId) => $value.kind === "func_id";
export type TypeId = $.TypeId;
export const TypeId = (text: string, loc: $.Range): $.TypeId =>
Object.freeze({
kind: "type_id",
text,
loc,
});
export const isTypeId = ($value: TypeId) => $value.kind === "type_id";
Loading
Loading