Skip to content

Implement multi-language support - #130

Open
msujew wants to merge 7 commits into
mainfrom
msujew/multi-language-support
Open

Implement multi-language support#130
msujew wants to merge 7 commits into
mainfrom
msujew/multi-language-support

Conversation

@msujew

@msujew msujew commented Jul 23, 2026

Copy link
Copy Markdown
Member

Closes #96

Does as the title says, similar to how it is outlined in the issue:

  • Adds a fastbelt/cmd package adopters can use to write their own CLIs to generate Fastbelt code.
  • Adds a LanguageSelector service that is used to determine during runtime what language a URI/document belongs to.
  • Implements a switch-case based selector in the parser and lexer to circumvent the need for a separate service instance per language.
  • Adds a multilang example that shows that this is working as expected (including parser, lexer and completion tests).

FYI, while this has a Plugins field in the API, plugins aren't actually supported in this PR. This will need a follow-up.

@cdietrich

Copy link
Copy Markdown

wondering about the common lexical scope and an option to have a lexer per entry rule
#131

@msujew
msujew force-pushed the msujew/multi-language-support branch from 78988e1 to 9f6d652 Compare July 27, 2026 14:14

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.50.

Benchmark suite Current: 40d792c Previous: d803417 Ratio
BenchmarkWorkspaceCycle (typefox.dev/fastbelt/examples/statemachine) - MB/s 13.16 MB/s 5.21 MB/s 2.53

This comment was automatically generated by workflow using github-action-benchmark.

@msujew

msujew commented Jul 27, 2026

Copy link
Copy Markdown
Member Author

@cdietrich Thanks for the input. I plan to finish implementing this once #127 lands, since it refactors a lot of the lexer infrastructure.

@msujew
msujew marked this pull request as ready for review August 5, 2026 14:00

@ssmifi ssmifi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks solid, thanks. I have a couple of questions to get a better understanding before merging and some documentation seems to be stale.

Comment thread cmd/fastbelt/generate.go
@@ -55,7 +55,7 @@ func runGenerateCLI(opts generateOptions) error {
}

sc := grammar.CreateServices()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice separation.
Question: The following lines are conceptionally doing for one file what parseAndMerge and reportDiagnostic do generically now. I was wondering if we can de-duplicate some code here and use come common helper?

Comment thread cmd/fastbelt/generate.go
Comment thread cmd/build.go
Comment thread cmd/build.go
Comment thread cmd/build.go
Comment thread workspace/builder.go
Comment thread workspace/initializer.go
Comment thread document.go
Comment thread language_selector.go Outdated

type DocumentMatcher func(uri URI) bool

// DocumentFilter matches a document by LSP language id and/or a glob over the

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DocumentSelector?

Comment thread language_selector.go
"typefox.dev/fastbelt/util/service"
)

type DocumentMatcher func(uri URI) bool

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this is an exported symbol, it should probably get a doc, even if self-explanatory.

service.Put[core.LanguageSelector](
sc,
core.NewDefaultLanguageSelector(sc,
core.NewDocumentSelectorWithPatterns("arithmetics", "**/*.arithmetics"),

@Lotes Lotes Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Puh, a document selector can also influence the folders up the file hierarchy. Also here you seem to be forced to use „**/“… this is broader than an array of file extensions. Not sure if we should go for this. You always need to prepend „**/*“ to your „.ext“.
Is this case-insensitive btw?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also here you seem to be forced to use „**/“… this is broader than an array of file extensions.

You're not forced to do it. Adopters can implement their own FileExtensionDocumentSelector if they want to. If absolutely required, we can also implement this in the framework, but I'm not really convinced that this is better than the glob pattern.

I'm not happy how this works in Langium, because the idea to use file extensions as the defining identifying feature of languages has a large negative impact on the API design.

Is this case-insensitive btw?

No, but neither is Langium's file extension comparison AFAIK.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I am not really for or against it. It just feels unusual.
But it serves the same purpose as before and goes even beyond that, which might be a good sign to keep it.

Comment thread cmd/build.go
// documents.
type Language struct {
Entry string
LanguageID string

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a lexer mode, after #127 is merged.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or combine it within the syntax of the entry rule:

entry XRule on mode YMode: ...

Omitting on mode YMode falls back to the default mode.

@@ -0,0 +1,15 @@
grammar MultilangModel

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought this PR is also about multi file support.
But yes, this might be a smaller step towards this direction.

Comment thread document.go
DocStateLocalSymbols // 0x0010
// DocStateLinked marks that cross-references were linked.
DocStateLinked // 0x0010
DocStateLinked // 0x0020

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the comment "//0x0001" ...? Who needs it?
The only reason in my eyes: to not forget the flag nature of this constant group.

Alternative: Rename the constants to reflect the flag nature.

  • DocStateFlagLinked
  • DocStateBitMaskLinked

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Improvement] Support multi-language setups

4 participants