Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More for LOX #32

Merged
merged 15 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from 14 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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
.vscode-test/
coverage/
dist/
bin/
lib/
out/
node_modules/
*.vsix
*.tsbuildinfo
generated/
/**/generated/
8 changes: 8 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
"args": [
"--extensionDevelopmentPath=${workspaceFolder}/examples/ox",
"${workspaceFolder}/examples/ox/examples"
],
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/examples/ox/out/**/*.js"
]
},
{
Expand All @@ -21,6 +25,10 @@
"args": [
"--extensionDevelopmentPath=${workspaceFolder}/examples/lox",
"${workspaceFolder}/examples/lox/examples"
],
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/examples/lox/out/**/*.js"
]
},
{
Expand Down
13 changes: 0 additions & 13 deletions examples/lox/.eslintrc.json

This file was deleted.

3 changes: 0 additions & 3 deletions examples/lox/.gitignore

This file was deleted.

4 changes: 0 additions & 4 deletions examples/lox/.vscodeignore

This file was deleted.

2 changes: 1 addition & 1 deletion examples/lox/langium-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"grammar": "src/language/lox.langium",
"fileExtensions": [".lox"],
"textMate": {
"out": "syntaxes/lox.tmLanguage.json"
"out": "./syntaxes/lox.tmLanguage.json"
}
}],
"out": "src/language/generated"
Expand Down
12 changes: 7 additions & 5 deletions examples/lox/src/language/lox-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@
* terms of the MIT License, which is available in the project root.
******************************************************************************/

import { DefaultSharedCoreModuleContext, LangiumCoreServices, LangiumSharedCoreServices, Module, PartialLangiumCoreServices, createDefaultCoreModule, createDefaultSharedCoreModule, inject } from 'langium';
import { Module, PartialLangiumCoreServices, createDefaultCoreModule, inject } from 'langium';
import { DefaultSharedModuleContext, LangiumServices, LangiumSharedServices, createDefaultSharedModule } from 'langium/lsp';
import { LangiumServicesForTypirBinding, createLangiumModuleForTypirBinding, initializeLangiumTypirServices } from 'typir-langium';
import { LoxGeneratedModule, LoxGeneratedSharedModule } from './generated/module.js';
import { LoxScopeProvider } from './lox-scope.js';
import { LoxValidationRegistry, LoxValidator } from './lox-validator.js';
import { DefaultSharedModuleContext, LangiumServices, LangiumSharedServices, createDefaultSharedModule } from 'langium/lsp';
import { createLangiumModuleForTypirBinding, initializeLangiumTypirServices, LangiumServicesForTypirBinding } from 'typir-langium';
import { createLoxTypirModule } from './type-system/lox-type-checking.js';
import { registerValidationChecks } from 'langium/grammar';

/**
* Declaration of custom services - add your own service classes here.
Expand Down Expand Up @@ -54,6 +53,9 @@ export const LoxModule: Module<LoxServices, PartialLangiumCoreServices & LoxAdde
* - Langium default language-specific services
* - Services generated by langium-cli
* - Services specified in this file
* For type checking with Typir, merge two more modules:
* - Typir default services
* - custom services for LOX
*
* @param context Optional module context with the LSP connection
* @returns An object wrapping the shared services and the language-specific services
Expand All @@ -69,8 +71,8 @@ export function createLoxServices(context: DefaultSharedModuleContext): {
const Lox = inject(
createDefaultCoreModule({ shared }),
LoxGeneratedModule,
createLangiumModuleForTypirBinding(shared),
LoxModule,
createLangiumModuleForTypirBinding(shared),
createLoxTypirModule(shared),
);
shared.ServiceRegistry.register(Lox);
Expand Down
8 changes: 4 additions & 4 deletions examples/lox/src/language/lox-scope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
* terms of the MIT License, which is available in the project root.
******************************************************************************/

import { DefaultScopeProvider, EMPTY_SCOPE, AstUtils, ReferenceInfo, Scope, LangiumCoreServices } from "langium";
import { Class, isClass, MemberCall } from "./generated/ast.js";
import { isClassType } from "./type-system/descriptions.js";
import { getClassChain, inferType } from "./type-system/infer.js";
import { DefaultScopeProvider, EMPTY_SCOPE, AstUtils, ReferenceInfo, Scope, LangiumCoreServices } from 'langium';
import { Class, isClass, MemberCall } from './generated/ast.js';
import { isClassType } from './type-system/descriptions.js';
import { getClassChain, inferType } from './type-system/infer.js';

export class LoxScopeProvider extends DefaultScopeProvider {

Expand Down
37 changes: 2 additions & 35 deletions examples/lox/src/language/lox-validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@
* terms of the MIT License, which is available in the project root.
******************************************************************************/

import { AstNode, ValidationAcceptor, ValidationChecks, ValidationRegistry } from 'langium';
import { BinaryExpression, LoxAstType, VariableDeclaration } from './generated/ast.js';
import { ValidationAcceptor, ValidationChecks, ValidationRegistry } from 'langium';
import { LoxAstType, VariableDeclaration } from './generated/ast.js';
import type { LoxServices } from './lox-module.js';
import { TypeDescription } from './type-system/descriptions.js';
import { inferType } from './type-system/infer.js';
import { isLegalOperation } from './type-system/operator.js';

/**
* Registry for validation checks.
Expand All @@ -19,7 +16,6 @@ export class LoxValidationRegistry extends ValidationRegistry {
super(services);
const validator = services.validation.LoxValidator;
const checks: ValidationChecks<LoxAstType> = {
BinaryExpression: validator.checkBinaryOperationAllowed,
VariableDeclaration: validator.checkVariableDeclaration,
};
this.register(checks, validator);
Expand All @@ -41,33 +37,4 @@ export class LoxValidator {
}
}

checkBinaryOperationAllowed(binary: BinaryExpression, accept: ValidationAcceptor): void {
const map = this.getTypeCache();
const left = inferType(binary.left, map);
const right = inferType(binary.right, map);
if (!isLegalOperation(binary.operator, left, right)) {
// accept('error', `Cannot perform operation '${binary.operator}' on values of type '${typeToString(left)}' and '${typeToString(right)}'.`, {
// node: binary
// })
} else if (binary.operator === '=') {
// if (!isAssignable(right, left)) {
// accept('error', `Type '${typeToString(right)}' is not assignable to type '${typeToString(left)}'.`, {
// node: binary,
// property: 'right'
// })
// }
} else if (['==', '!='].includes(binary.operator)) {
// if (!isAssignable(right, left)) {
// accept('warning', `This comparison will always return '${binary.operator === '==' ? 'false' : 'true'}' as types '${typeToString(left)}' and '${typeToString(right)}' are not compatible.`, {
// node: binary,
// property: 'operator'
// });
// }
}
}

private getTypeCache(): Map<AstNode, TypeDescription> {
return new Map();
}

}
4 changes: 2 additions & 2 deletions examples/lox/src/language/type-system/assignment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
* This program and the accompanying materials are made available under the
* terms of the MIT License, which is available in the project root.
******************************************************************************/
import { isClassType, isFunctionType, isNilType, TypeDescription } from "./descriptions.js";
import { getClassChain } from "./infer.js";
import { isClassType, isFunctionType, isNilType, TypeDescription } from './descriptions.js';
import { getClassChain } from './infer.js';

export function isAssignable(from: TypeDescription, to: TypeDescription): boolean {
if (isClassType(from)) {
Expand Down
54 changes: 27 additions & 27 deletions examples/lox/src/language/type-system/descriptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
* terms of the MIT License, which is available in the project root.
******************************************************************************/

import { AstNode } from "langium";
import { BooleanLiteral, Class, NumberLiteral, StringLiteral } from "../generated/ast.js"
import { AstNode } from 'langium';
import { BooleanLiteral, Class, NumberLiteral, StringLiteral } from '../generated/ast.js';

export type TypeDescription =
| NilTypeDescription
Expand All @@ -18,83 +18,83 @@ export type TypeDescription =
| ErrorType;

export interface NilTypeDescription {
readonly $type: "nil"
readonly $type: 'nil'
}

export function createNilType(): NilTypeDescription {
return {
$type: "nil"
$type: 'nil'
};
}

export function isNilType(item: TypeDescription): item is NilTypeDescription {
return item.$type === "nil";
return item.$type === 'nil';
}

export interface VoidTypeDescription {
readonly $type: "void"
readonly $type: 'void'
}

export function createVoidType(): VoidTypeDescription {
return {
$type: "void"
}
$type: 'void'
};
}

export function isVoidType(item: TypeDescription): item is VoidTypeDescription {
return item.$type === "void";
return item.$type === 'void';
}

export interface BooleanTypeDescription {
readonly $type: "boolean"
readonly $type: 'boolean'
readonly literal?: BooleanLiteral
}

export function createBooleanType(literal?: BooleanLiteral): BooleanTypeDescription {
return {
$type: "boolean",
$type: 'boolean',
literal
};
}

export function isBooleanType(item: TypeDescription): item is BooleanTypeDescription {
return item.$type === "boolean";
return item.$type === 'boolean';
}

export interface StringTypeDescription {
readonly $type: "string"
readonly $type: 'string'
readonly literal?: StringLiteral
}

export function createStringType(literal?: StringLiteral): StringTypeDescription {
return {
$type: "string",
$type: 'string',
literal
};
}

export function isStringType(item: TypeDescription): item is StringTypeDescription {
return item.$type === "string";
return item.$type === 'string';
}

export interface NumberTypeDescription {
readonly $type: "number",
readonly $type: 'number',
readonly literal?: NumberLiteral
}

export function createNumberType(literal?: NumberLiteral): NumberTypeDescription {
return {
$type: "number",
$type: 'number',
literal
};
}

export function isNumberType(item: TypeDescription): item is NumberTypeDescription {
return item.$type === "number";
return item.$type === 'number';
}

export interface FunctionTypeDescription {
readonly $type: "function"
readonly $type: 'function'
readonly returnType: TypeDescription
readonly parameters: FunctionParameter[]
}
Expand All @@ -106,48 +106,48 @@ export interface FunctionParameter {

export function createFunctionType(returnType: TypeDescription, parameters: FunctionParameter[]): FunctionTypeDescription {
return {
$type: "function",
$type: 'function',
parameters,
returnType
};
}

export function isFunctionType(item: TypeDescription): item is FunctionTypeDescription {
return item.$type === "function";
return item.$type === 'function';
}

export interface ClassTypeDescription {
readonly $type: "class"
readonly $type: 'class'
readonly literal: Class
}

export function createClassType(literal: Class): ClassTypeDescription {
return {
$type: "class",
$type: 'class',
literal
};
}

export function isClassType(item: TypeDescription): item is ClassTypeDescription {
return item.$type === "class";
return item.$type === 'class';
}

export interface ErrorType {
readonly $type: "error"
readonly $type: 'error'
readonly source?: AstNode
readonly message: string
}

export function createErrorType(message: string, source?: AstNode): ErrorType {
return {
$type: "error",
$type: 'error',
message,
source
};
}

export function isErrorType(item: TypeDescription): item is ErrorType {
return item.$type === "error";
return item.$type === 'error';
}

export function typeToString(item: TypeDescription): string {
Expand Down
6 changes: 3 additions & 3 deletions examples/lox/src/language/type-system/infer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
* terms of the MIT License, which is available in the project root.
******************************************************************************/

import { AstNode } from "langium";
import { BinaryExpression, Class, isBinaryExpression, isBooleanLiteral, isClass, isFieldMember, isFunctionDeclaration, isMemberCall, isMethodMember, isNilLiteral, isNumberLiteral, isParameter, isPrintStatement, isReturnStatement, isStringLiteral, isTypeReference, isUnaryExpression, isVariableDeclaration, MemberCall, TypeReference } from "../generated/ast.js";
import { createBooleanType, createClassType, createErrorType, createFunctionType, createNilType, createNumberType, createStringType, createVoidType, isFunctionType, isStringType, TypeDescription } from "./descriptions.js";
import { AstNode } from 'langium';
import { BinaryExpression, Class, isBinaryExpression, isBooleanLiteral, isClass, isFieldMember, isFunctionDeclaration, isMemberCall, isMethodMember, isNilLiteral, isNumberLiteral, isParameter, isPrintStatement, isReturnStatement, isStringLiteral, isTypeReference, isUnaryExpression, isVariableDeclaration, MemberCall, TypeReference } from '../generated/ast.js';
import { createBooleanType, createClassType, createErrorType, createFunctionType, createNilType, createNumberType, createStringType, createVoidType, isFunctionType, isStringType, TypeDescription } from './descriptions.js';

export function inferType(node: AstNode | undefined, cache: Map<AstNode, TypeDescription>): TypeDescription {
let type: TypeDescription | undefined;
Expand Down
Loading