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

Tree-sitter grammar: add support for module declaration #5385

Merged
merged 5 commits into from
Jun 12, 2024
Merged
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
514 changes: 290 additions & 224 deletions backend/testfiles/execution/stdlib/semanticTokenization.dark

Large diffs are not rendered by default.

41 changes: 41 additions & 0 deletions backend/tests/Tests/NewParser.Tests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,46 @@ let functionDeclarations =
"let sum (a: Int64) (b: Int64): Int64 =\n PACKAGE.Darklang.Stdlib.Int64.add a b" ]
|> testList "function declarations"

let moduleDeclarations =
[ t
"simple module"
"module MyModule =\n type ID = Int64"
"module MyModule =\n type ID =\n Int64"

t
"module with types, fns, and consts"
"""module MyModule =
type ID = Int64
type MyString = String
let myFn (i: Int64): Int64 = 1L
const x = 100L"""
"module MyModule =\n type ID =\n Int64\n\n type MyString =\n String\n\n let myFn (i: Int64): Int64 =\n 1L\n\n const x = 100L"

t
"module with types, fns, conts, and newlines"
"""module MyModule =
type ID = Int64

type MyString = String

let myFn (i: Int64): Int64 = 1L

const x = 100L"""
"module MyModule =\n type ID =\n Int64\n\n type MyString =\n String\n\n let myFn (i: Int64): Int64 =\n 1L\n\n const x = 100L"

t
"nested module declaration"
"""module MyModule1 =
type ID = Int64
module MyModule2 =
type ID = Int64
module MyModule3 =
type ID = Int64
const x = 100L
1L"""
"module MyModule1 =\n type ID =\n Int64\n\n module MyModule2 =\n type ID =\n Int64\n\n module MyModule3 =\n type ID =\n Int64\n\n const x = 100L\n\n 1L" ]
|> testList "module declarations"


let cliScripts =
[
Expand Down Expand Up @@ -806,4 +846,5 @@ let tests =
constantDeclarations
exprs
functionDeclarations
moduleDeclarations
cliScripts ]
9 changes: 9 additions & 0 deletions packages/darklang/languageTools/parser/cliScript.dark
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ module Darklang =
{ result with
exprsToEval = Stdlib.List.pushBack result.exprsToEval parsedExpr }

| "module_decl" ->
match ModuleDeclaration.parse decl with
| Error e -> updateUnparseableStuff result e
| Ok parsedModuleDecl ->
let newModule =
WrittenTypes.CliScriptDeclaration.Module parsedModuleDecl

{ result with
declarations = Stdlib.List.pushBack result.declarations newModule }
| _ ->
updateUnparseableStuff
result
Expand Down
60 changes: 60 additions & 0 deletions packages/darklang/languageTools/parser/moduleDeclaration.dark
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
module Darklang =
module LanguageTools =
module Parser =
module ModuleDeclaration =
let parseDecls
(node: ParsedNode)
: Stdlib.Result.Result<WrittenTypes.ModuleDeclaration.Declaration, WrittenTypes.Unparseable> =
match node.typ with
| "type_decl" ->
(TypeDeclaration.parse node)
|> Stdlib.Result.map (fun x ->
WrittenTypes.ModuleDeclaration.Declaration.Type x)
| "fn_decl" ->
(FunctionDeclaration.parse node)
|> Stdlib.Result.map (fun x ->
WrittenTypes.ModuleDeclaration.Declaration.Function x)
| "const_decl" ->
(ConstantDeclaration.parse node)
|> Stdlib.Result.map (fun x ->
WrittenTypes.ModuleDeclaration.Declaration.Constant x)
| "module_decl" ->
(ModuleDeclaration.parse node)
|> Stdlib.Result.map (fun x ->
WrittenTypes.ModuleDeclaration.Declaration.SubModule x)
| "expression" ->
(Expr.parse node)
|> Stdlib.Result.map (fun x ->
WrittenTypes.ModuleDeclaration.Declaration.Expr x)
| _ -> createUnparseableError node

let parse
(node: ParsedNode)
: Stdlib.Result.Result<WrittenTypes.ModuleDeclaration.ModuleDeclaration, WrittenTypes.Unparseable> =
if node.typ == "module_decl" then
let keywordModule = findField node "keyword_module"
let name = (findField node "name") |> Builtin.unwrap

let declarations =
(Stdlib.List.filter node.children (fun node ->
node.typ == "module_content"))
|> Stdlib.List.map (fun node ->
node.children
|> Stdlib.List.head
|> Builtin.unwrap
|> ModuleDeclaration.parseDecls)
|> Stdlib.Result.collect

match keywordModule, declarations with
| Ok keywordModule, Ok declarations ->
(WrittenTypes.ModuleDeclaration.ModuleDeclaration
{ range = node.range
name = (name.range, name.text)
declarations = declarations
keywordModule = keywordModule.range })
|> Stdlib.Result.Result.Ok

| _ -> createUnparseableError node

else
createUnparseableError node
7 changes: 7 additions & 0 deletions packages/darklang/languageTools/programTypes.dark
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,12 @@ module Darklang =
constants: List<PackageConstant.PackageConstant>
fns: List<PackageFn.PackageFn> }

type Definitions =
{ types: List<PackageType.PackageType>
constants: List<PackageConstant.PackageConstant>
fns: List<PackageFn.PackageFn>
// TODO db and handlers
exprs: List<Expr * List<String>> }

// User/Canvas space
type DB =
Expand Down Expand Up @@ -451,6 +457,7 @@ module Darklang =
| Type of PackageType.PackageType
| Constant of PackageConstant.PackageConstant
| Function of PackageFn.PackageFn
| Module of Definitions

type CliScript =
{ declarations: List<Declaration>
Expand Down
28 changes: 27 additions & 1 deletion packages/darklang/languageTools/semanticTokens.dark
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,30 @@ module Darklang =
| QualifiedName q -> QualifiedTypeIdentifier.tokenize q


module ModuleDeclaration =
let tokenizeDeclaration
(d: WrittenTypes.ModuleDeclaration.Declaration)
: List<SemanticToken> =
match d with
| Type t -> TypeDeclaration.tokenize t
| Function f -> FnDeclaration.tokenize f
| Constant c -> ConstantDeclaration.tokenize c
| SubModule sm -> ModuleDeclaration.tokenize sm
| Expr e -> Expr.tokenize e

let tokenize
(m: WrittenTypes.ModuleDeclaration.ModuleDeclaration)
: List<SemanticToken> =
let (nameRange, name) = m.name

[ [ makeToken m.keywordModule TokenType.Keyword ]
[ makeToken nameRange TokenType.ModuleName ]
(m.declarations
|> Stdlib.List.map (fun d -> ModuleDeclaration.tokenizeDeclaration d)
|> Stdlib.List.flatten) ]
|> Stdlib.List.flatten


module TypeDeclaration =
let tokenizeDefinition
(d: WrittenTypes.TypeDeclaration.Definition)
Expand Down Expand Up @@ -1028,6 +1052,7 @@ module Darklang =
|> Stdlib.List.flatten) ]
|> Stdlib.List.flatten


module Const =
let tokenize (c: WrittenTypes.Const) : List<SemanticToken> =
match c with
Expand Down Expand Up @@ -1214,7 +1239,8 @@ module Darklang =
match typeOrFn with
| Type t -> TypeDeclaration.tokenize t
| Function fn -> FnDeclaration.tokenize fn
| Constant c -> ConstantDeclaration.tokenize c)
| Constant c -> ConstantDeclaration.tokenize c
| Module m -> ModuleDeclaration.tokenize m)
|> Stdlib.List.flatten

let exprsPart =
Expand Down
28 changes: 24 additions & 4 deletions packages/darklang/languageTools/writtenTypes.dark
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,24 @@ module Darklang =
fields: List<Const> *
symbolDot: Range


// Module declarations
module ModuleDeclaration =
type Declaration =
| Type of TypeDeclaration.TypeDeclaration
| Function of FnDeclaration.FnDeclaration
| Constant of ConstantDeclaration.ConstantDeclaration
| SubModule of ModuleDeclaration.ModuleDeclaration
// TODO: handle http handler and db
| Expr of Expr

type ModuleDeclaration =
{ range: Range
name: Range * String
declarations: List<Declaration>
keywordModule: Range }


// Fn declarations
module FnDeclaration =
type UnitParameter = { range: Range }
Expand Down Expand Up @@ -475,15 +493,17 @@ module Darklang =
keywordConst: Range
symbolEquals: Range }

type Unparseable =
{ source: Parser.ParsedNode
note: Stdlib.Option.Option<String> }

// Cli scripts (CLEANUP throw both of these types in a CliScript module)
type CliScriptDeclaration =
| Type of TypeDeclaration.TypeDeclaration
| Function of FnDeclaration.FnDeclaration
| Constant of ConstantDeclaration.ConstantDeclaration
| Module of ModuleDeclaration.ModuleDeclaration

type Unparseable =
{ source: Parser.ParsedNode
note: Stdlib.Option.Option<String> }


type CliScript =
{ range: Range
Expand Down
Loading