-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- functions and operators can be annotated with validations now - Typir module: - reorganized the grouping of services - don't merge Langium+Typir services, but provide the Typir services via an "typir"-property/service within the Langium services - override only selected services of a group - extracted missing service interface - extracted logic to resolve TypeSelectors into its own service to make the implementation exchangable - the module now looks into the kind registry, whether the kind is already initialized, before a new one is created (this partially fulfills #44) - removed dependencies to 'langium/lsp' from Typir-Langium in order to use it also in non-LSP projects - switched to Langium v3.3, simplified API, removed duplicated code for a fix which is part of Langium 3.3 now - added missing READMEs, ChangeLog, added content, added EclipseCon slides - associate domain elements with Typir types - implemented overloaded functions and methods in LOX by using Typir already during Linking! - reduced code for the "Tiny Typir" example a bit
- Loading branch information
1 parent
cfbe123
commit b1cb1fb
Showing
76 changed files
with
1,831 additions
and
1,571 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Typir Change Log | ||
|
||
We roughly follow the ideas of [semantic versioning](https://semver.org/). | ||
Note that the versions "0.x.0" probably will include breaking changes. | ||
|
||
|
||
## v0.1.0 (December 2024) | ||
|
||
This is the first official release of Typir. | ||
It serves as first version to experiment with Typir and to gather feedback to guide and improve the upcoming versions. We are looking forward to your feedback! | ||
|
||
- [Linked issues and PRs](https://github.com/TypeFox/typir/milestone/2) | ||
- Core implementations of the following [type-checking services](/packages/typir/src/services/): | ||
- Assignability | ||
- Equality | ||
- Conversion (implicit/coercion and explicit/casting) | ||
- Type inference | ||
- Sub-typing | ||
- Validation | ||
- Caching | ||
- [Predefined types](/packages/typir/src/kinds/) to reuse: | ||
- Primitives | ||
- Functions (with overloading) | ||
- Classes (nominally typed) | ||
- Top, bottom | ||
- (some more are under development) | ||
- Operators (which are mapped to Functions, with overloading) | ||
- Application examples: | ||
- LOX (without lambdas) | ||
- OX |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,20 @@ | ||
# Contributing | ||
|
||
TODO | ||
|
||
|
||
## Communication | ||
|
||
The following communication channels are available: | ||
|
||
- [GitHub issues](https://github.com/TypeFox/typir/issues) - for bug reports, feature requests, etc. | ||
- [GitHub discussions](https://github.com/TypeFox/typir/discussions) - for questions, ideas, announcements, etc. | ||
- [Weekly Langium dev meeting](https://github.com/eclipse-langium/langium/discussions/564?sort=new) - While Typir is independent from Langium in general, you might meet some Typir developers at the Langium dev meetings. | ||
|
||
In case you have a question, please look into the provided resources and documentations first. | ||
If you don't find any answer there, feel free to use the discussions to get help. | ||
|
||
|
||
## Release Process | ||
|
||
The release process for Typir is described in [RELEASE.md](./RELEASE.md). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,90 @@ | ||
# Typir | ||
|
||
Engineering types for software languages in the web. | ||
<div id="badges" align="center"> | ||
|
||
[![npm](https://img.shields.io/npm/v/typir)](https://www.npmjs.com/package/typir) | ||
[![Build](https://github.com/TypeFox/typir/actions/workflows/actions.yml/badge.svg)](https://github.com/TypeFox/typir/actions/workflows/actions.yml) | ||
[![Github Discussions](https://img.shields.io/badge/github-discussions-blue?logo=github)](https://github.com/TypeFox/typir/discussions) | ||
[![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-ready--to--code-FFAE33?logo=gitpod)](https://gitpod.io/#https://github.com/TypeFox/typir) | ||
|
||
</div> | ||
|
||
--- | ||
|
||
Typir is a library for type systems and type checking for software languages in the web. | ||
|
||
Typir is OpenSource, written in TypeScript, and follows pragmatic approaches for easing type checking in practical language engineering projects by providing default implementations for recurring problems. | ||
As a stand-alone library, Typir provides a TypeScript-API for language engineers without an additional, external DSL for formalizing types. | ||
|
||
|
||
## Core Features | ||
|
||
Typir provides these core features: | ||
|
||
- Predefined types: | ||
- primitives | ||
- functions (with overloading) | ||
- classes | ||
- top, bottom | ||
- (more are planned) | ||
- Solutions for: circular type definitions, caching, operators | ||
- Meaningful and customizable error messages | ||
- The provided default implementations are customizable by dependency injection | ||
|
||
Typir does intentionally _not_ include ... | ||
|
||
- rules engines and constraint solving | ||
- formal proofs | ||
- external DSLs for formalizing types | ||
|
||
|
||
## NPM workspace | ||
|
||
This repository is a NPM workspace. It contains the following packages: | ||
|
||
- [Typir](./packages/typir/README.md) - the core package of Typir | ||
- [Typir-Langium](./packages/typir-langium/README.md) - a integration of Typir for [Langium](https://github.com/eclipse-langium/langium) | ||
- [Typir](./packages/typir/README.md) - the core package of Typir with default implementations for type checking services and some predefined types | ||
- [Typir-Langium](./packages/typir-langium/README.md) - a binding of Typir for [Langium](https://github.com/eclipse-langium/langium), a language workbench for developing textual DSLs in the web, | ||
in order to ease type checking for Langium-based languages | ||
|
||
This repository contains the following stand-alone applications, which demonstrate how to use Typir for type checking: | ||
|
||
- [LOX](./examples/lox/README.md) - static type checking for LOX, implemented with Typir-Langium | ||
- [OX](./examples/ox/README.md) - a reduced version of LOX, implemented with Typir-Langium | ||
|
||
|
||
## Tiny Typir Example | ||
|
||
[TODO](/packages/typir/test/api-example.test.ts) | ||
|
||
|
||
## Resources | ||
|
||
Typir is presented in these talks: | ||
|
||
- [LangDev'24](https://langdevcon.org/2024/program#26): [Video](https://www.youtube.com/watch?v=CL8EbJYeyTE), [slides](/resources/talks/2024-10-17-LangDev.pdf) (2024-10-17) | ||
- [OCX/EclipseCon'24](https://www.ocxconf.org/event/778b82cc-6834-48a4-a58e-f883c5a7b8c9/agenda?session=23b97df9-0435-4fab-8a01-e0a9cf3e3831&shareLink=true): [Video](https://www.youtube.com/watch?v=WLzXAhcl-aY&list=PLy7t4z5SYNaRRGVdF83feN-_uHLwvGvgw&index=23), [slides](/resources/talks/2024-10-24-EclipseCon.pdf) (2024-10-24) | ||
|
||
|
||
## Roadmap | ||
|
||
The roadmap of Typir is organized with [milestones in GitHub](https://github.com/TypeFox/typir/milestones). | ||
|
||
The roadmap include, among other, these features: | ||
|
||
- More predefined types: structurally typed classes, lambdas, generics, constrained primitive types (e.g. numbers with upper and lower bound), ... | ||
- Calculate types, e.g. operators whose return types depend on their current input types | ||
- Optimized APIs to register rules for inference and validation | ||
|
||
For the released versions of Typir, see the [CHANGELOG.md](/CHANGELOG.md). | ||
|
||
|
||
## Contributing | ||
|
||
Please read the [CONTRIBUTING.md](./CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us. | ||
|
||
We also have a release process described in [RELEASE.md](./RELEASE.md). | ||
|
||
|
||
## License | ||
|
||
[MIT License](/LICENSE) | ||
Typir is fully [MIT licensed](/LICENSE). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Typir applied to LOX | ||
|
||
This package contains an adapted version of [LOX](https://craftinginterpreters.com/the-lox-language.html), [realized with Langium](https://github.com/TypeFox/langium-lox) and statically type-checked with [Typir](https://typir.org/). | ||
|
||
Typir is used here to make LOX a statically typed language: | ||
|
||
- Variables have one type, which is either explicitly declared (e.g. `var v1: string`) or derived from the initial value (e.g. `var v2: 2 <= 3`). | ||
- Lox supports these types here: | ||
- primitives: boolean, string, number, void | ||
- Classes (nominally typed) | ||
- Lambdas (not yet supported) | ||
- We keep `nil`, but it can be assigned only to variables with a class or lambda as type. | ||
Variables with primitive type and without explicit initial value have the primitive types default value. | ||
|
||
For examples written in LOX, look at some [collected examples](./examples/) or the [test cases](./test/). | ||
|
||
To compare the current implementation for type checking with Typir with an implementation without Typir, have a look into [this repository](https://github.com/TypeFox/langium-lox/tree/main/langium/src/language-server/type-system). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/****************************************************************************** | ||
* Copyright 2024 TypeFox GmbH | ||
* This program and the accompanying materials are made available under the | ||
* terms of the MIT License, which is available in the project root. | ||
******************************************************************************/ | ||
|
||
import { AstNodeDescription, DefaultLinker, LinkingError, ReferenceInfo } from 'langium'; | ||
import { isType } from '../../../../packages/typir/lib/graph/type-node.js'; | ||
import { TypirServices } from '../../../../packages/typir/lib/typir.js'; | ||
import { isClass, isFunctionDeclaration, isMemberCall, isMethodMember } from './generated/ast.js'; | ||
import { LoxServices } from './lox-module.js'; | ||
|
||
export class LoxLinker extends DefaultLinker { | ||
protected readonly typir: TypirServices; | ||
|
||
constructor(services: LoxServices) { | ||
super(services); | ||
this.typir = services.typir; | ||
} | ||
|
||
override getCandidate(refInfo: ReferenceInfo): AstNodeDescription | LinkingError { | ||
const container = refInfo.container; | ||
if (isMemberCall(container) && container.explicitOperationCall) { | ||
// handle overloaded functions/methods | ||
const scope = this.scopeProvider.getScope(refInfo); | ||
const calledDescriptions = scope.getAllElements().filter(d => d.name === refInfo.reference.$refText).toArray(); // same name | ||
if (calledDescriptions.length === 1) { | ||
return calledDescriptions[0]; // no overloaded functions/methods | ||
} if (calledDescriptions.length >= 2) { | ||
// in case of overloaded functions/methods, do type inference for given arguments | ||
const argumentTypes = container.arguments.map(arg => this.typir.Inference.inferType(arg)).filter(isType); | ||
if (argumentTypes.length === container.arguments.length) { // for all given arguments, a type is inferred | ||
for (const calledDescription of calledDescriptions) { | ||
const called = this.loadAstNode(calledDescription); | ||
if (isClass(called)) { | ||
// special case: call of the constructur, without any arguments/parameters | ||
return calledDescription; // there is only one constructor without any parameters | ||
} | ||
if ((isMethodMember(called) || isFunctionDeclaration(called)) && called.parameters.length === container.arguments.length) { // same number of arguments | ||
// infer expected types of parameters | ||
const parameterTypes = called.parameters.map(p => this.typir.Inference.inferType(p)).filter(isType); | ||
if (parameterTypes.length === called.parameters.length) { // for all parameters, a type is inferred | ||
if (argumentTypes.every((arg, index) => this.typir.Assignability.isAssignable(arg, parameterTypes[index]))) { | ||
return calledDescription; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
// no matching method is found, return the first found method => linking works + validation issues regarding the wrong parameter values can be shown! | ||
return calledDescriptions[0]; | ||
|
||
// the following approach does not work, since the container's cross-references are required for type inference, but they are not yet resolved | ||
// const type = this.typir.Inference.inferType(container); | ||
// if (isFunctionType(type)) { | ||
// return type.associatedDomainElement; | ||
// } | ||
} | ||
return this.createLinkingError(refInfo); | ||
} | ||
return super.getCandidate(refInfo); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.