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

Props drilling, anonymous Interfaces, working filter, meta everywhere, etc #799

Merged
merged 28 commits into from
Dec 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
20e64dc
refactor(sourcecode): node.Deps -> node.DIArgs
emil14 Dec 6, 2024
58bdfa0
fix(compiler:irgen): deps drill (passing handlers through components)
emil14 Dec 6, 2024
e7408b3
feat(std): anonymous single ports in interfaces; re-implemented filte…
emil14 Dec 6, 2024
9ae995c
feat(examples/e2e): return filter test; add explicit any to ports; pr…
emil14 Dec 6, 2024
49a03e9
fix(builder): refs to core.Meta
emil14 Dec 6, 2024
4fc2901
fix(runtime:funcs:fmt): sig -> res
emil14 Dec 6, 2024
c927c16
refactor(compiler): meta and error
emil14 Dec 6, 2024
8296745
refactor(compiler): meta, location and mod-ref, to core, update scope…
emil14 Dec 6, 2024
47555a0
refactor(irgen): get rid of compiler error
emil14 Dec 6, 2024
f60f372
fix(desugarer): upd after refactorign with core
emil14 Dec 6, 2024
2c4b42c
feat(parser): fill meta for each entity at each parsing step
emil14 Dec 6, 2024
0d1d1f9
feat(analyzer:error_handling): fill location from entity instead of s…
emil14 Dec 6, 2024
90b669d
fix(di): bump
emil14 Dec 7, 2024
d68c90f
fix(examples,e2e:interfaces): anonymous single-ports
emil14 Dec 7, 2024
b9773ee
feat(deps): nevalang/x to 0016
emil14 Dec 7, 2024
8aa1e8e
refactor(compiler): move graphReduction to IR package, move its call …
emil14 Dec 7, 2024
6383565
wip(irgen): di drilling
emil14 Dec 8, 2024
ffb7907
feat(lsp): fix bug when module found up to workspace and we see its p…
emil14 Dec 10, 2024
dcc469d
fix(cli): trim tailing / when `neva run` or `neva build` are executed
emil14 Dec 10, 2024
b40fa5b
fix(compiler): add missing path to fe result
emil14 Dec 10, 2024
2a6e792
refactor(std): port names
emil14 Dec 11, 2024
0f1be19
fix(compiler): add missing changes for port names refactoring
emil14 Dec 11, 2024
fc70d7c
wip(compiler): adding meta everywhere; feat(desugarer): reset counter…
emil14 Dec 13, 2024
bc697cf
fix(desugarer): do not reset counters, because that lead to overwriti…
emil14 Dec 15, 2024
3df29ae
fix(std:builtin): filter/split - unpack data before sending to predic…
emil14 Dec 15, 2024
adad78f
fix(desugarer): unit tests
emil14 Dec 15, 2024
330a5d2
feat(version): bump to 029 everywhere
emil14 Dec 15, 2024
ec41d5a
fix(examples,e2e): fix compile and runtime errors (analyzer doesn't c…
emil14 Dec 15, 2024
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ vendor
tmp
tmp.md
todo.md
docker-compose.yml
4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/cmd/neva",
"cwd": "${workspaceFolder}/e2e",
"args": ["run", "--trace", "tutorial/src"]
"cwd": "${workspaceFolder}/e2e/filter_list",
"args": ["run", "--trace", "main"]
},
{
"name": "DEBUG CODEGEN",
Expand Down
7 changes: 6 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,10 @@
"scrollbar.shadow": "#00000000"
},
"svg.preview.background": "dark-transparent",
"vsicons.presets.angular": true
"vsicons.presets.angular": true,
"editor.tokenColorCustomizations": {
"[One Dark Pro Flat]": {
"comments": "#7f848e82"
}
}
}
27 changes: 27 additions & 0 deletions benchmarks/simplest_message_passing/bench_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package test

import (
"os"
"os/exec"
"testing"

"github.com/stretchr/testify/require"
)

func BenchmarkMessagePassing(b *testing.B) {
err := os.Chdir("..")
require.NoError(b, err)

wd, err := os.Getwd()
require.NoError(b, err)
defer os.Chdir(wd)

b.ResetTimer()

for i := 0; i < b.N; i++ {
cmd := exec.Command("neva", "run", "message_passing")
_, err := cmd.CombinedOutput()
require.NoError(b, err)
require.Equal(b, 0, cmd.ProcessState.ExitCode())
}
}
5 changes: 5 additions & 0 deletions benchmarks/simplest_message_passing/main.neva
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
def Main(start any) (stop any) {
wait Wait
---
:start -> 1..1000 -> wait -> :stop
}
36 changes: 32 additions & 4 deletions cmd/lsp/indexer/indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package indexer

emil14 marked this conversation as resolved.
Show resolved Hide resolved
import (
"context"
"path/filepath"
"strings"

"github.com/nevalang/neva/internal/builder"
"github.com/nevalang/neva/internal/compiler"
Expand All @@ -15,12 +17,38 @@ type Indexer struct {
analyzer analyzer.Analyzer
}

func (i Indexer) FullIndex(ctx context.Context, path string) (src.Build, *compiler.Error) {
feResult, err := i.fe.Process(ctx, path)
func (i Indexer) FullScan(
ctx context.Context,
workspacePath string,
) (src.Build, bool, *compiler.Error) {
feResult, err := i.fe.Process(ctx, workspacePath)
if err != nil {
return src.Build{}, err
return src.Build{}, false, err
}
return i.analyzer.AnalyzeBuild(feResult.ParsedBuild)

// if nevalang module is found, but it's not part of the workspace
if isParentPath(workspacePath, feResult.Path) {
return src.Build{}, false, nil
}

aBuild, err := i.analyzer.AnalyzeBuild(feResult.ParsedBuild)
if err != nil {
return src.Build{}, false, err
}

return aBuild, true, nil
}

func isParentPath(parent, child string) bool {
parent = filepath.Clean(parent)
child = filepath.Clean(child)

rel, err := filepath.Rel(parent, child)
if err != nil {
return false
}

return !strings.HasPrefix(rel, "..")
}

func New(
Expand Down
1 change: 1 addition & 0 deletions cmd/lsp/server/general_messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

func (s *Server) Initialize(glspCtx *glsp.Context, params *protocol.InitializeParams) (any, error) {
s.workspacePath = *params.RootPath

return protocol.InitializeResult{
Capabilities: s.handler.CreateServerCapabilities(),
ServerInfo: &protocol.InitializeResultServerInfo{
Expand Down
21 changes: 15 additions & 6 deletions cmd/lsp/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,29 @@ type Server struct {
index *src.Build

problemsMutex *sync.Mutex
problemFiles map[string]struct{}
problemFiles map[string]struct{} // we only need to store file urls but not their problems

activeFile string
activeFileMutex *sync.Mutex
}

// indexAndNotifyProblems does full scan of the workspace
// and sends diagnostics if there are any problems
func (s *Server) indexAndNotifyProblems(notify glsp.NotifyFunc) error {
build, err := s.indexer.FullIndex(context.Background(), s.workspacePath)
build, found, proplems := s.indexer.FullScan(
context.Background(),
s.workspacePath,
)

if !found {
return nil
}

s.indexMutex.Lock()
s.index = &build
s.indexMutex.Unlock()

if err == nil {
if proplems == nil {
// clear problems
s.problemsMutex.Lock()
for uri := range s.problemFiles {
Expand All @@ -60,13 +69,13 @@ func (s *Server) indexAndNotifyProblems(notify glsp.NotifyFunc) error {

// remember problem and send diagnostic
s.problemsMutex.Lock()
uri := filepath.Join(s.workspacePath, err.Location.String())
uri := filepath.Join(s.workspacePath, proplems.Meta.Location.String())
s.problemFiles[uri] = struct{}{}
notify(
protocol.ServerTextDocumentPublishDiagnostics,
s.createDiagnostics(*err, uri),
s.createDiagnostics(*proplems, uri),
)
s.logger.Info("diagnostic sent:", "err", err)
s.logger.Info("diagnostic sent:", "err", proplems)
s.problemsMutex.Unlock()

return nil
Expand Down
4 changes: 2 additions & 2 deletions docs/book/directives.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ def Main(start any) (stop any) {
lock Lock<string>
---
:start -> lock:sig
greeting:msg -> lock:data
greeting:res -> lock:data
lock:data -> println:data
println:sig -> :stop
println:res -> :stop
}
```

Expand Down
14 changes: 7 additions & 7 deletions docs/book/program_structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,26 +36,26 @@ Module is usually a git-repo but not necessary. Module that isn't published in g

### Manifest File

The manifest defines the module's minimum supported language version and dependencies. Here's an example manifest with a dependency on the Nevalang compiler version `0.28.2` and a third-party module:
The manifest defines the module's minimum supported language version and dependencies. Here's an example manifest with a dependency on the Nevalang compiler version `0.29.0` and a third-party module:

```yaml
neva: 0.28.2
neva: 0.29.0
deps:
github.com/nevalang/x:
path: github.com/nevalang/x
version: 0.0.14
version: 0.0.16
```

The `deps` field is a map where each dependency has an alias. When adding dependencies via CLI (e.g., `neva get github.com/nevalang/x`), the package manager automatically inserts a key-value pair. Third-party dependencies must have a valid git-clone path and a fixed semver version. The package manager uses git to download the repo and looks for the corresponding git-tag. The alias typically defaults to the module's path, but custom aliases allow multiple versions of the same module:

> WIP: CLI tool planned for CI/CD to verify module's backward compatibility

```yaml
neva: 0.28.2
neva: 0.29.0
deps:
github.com/nevalang/x@0-0-12:
path: github.com/nevalang/x
version: 0.0.14
version: 0.0.16
github.com/nevalang/x@0-0-11:
path: github.com/nevalang/x
version: 0.0.11
Expand All @@ -71,7 +71,7 @@ Module references uniquely identify modules in a build, used by the compiler to

```yaml
path: github.com/nevalang/x
version: 0.0.14
version: 0.0.16
```

### Entry Module
Expand Down Expand Up @@ -312,7 +312,7 @@ Third-party imports are imports of packages located in third-party modules - mod
deps:
github.com/nevalang/x:
path: github.com/nevalang/x
version: 0.0.14
version: 0.0.16
```

Then when you `import { github.com/nevalang/x }` compiler will know exactly path and version of the module you are referring to.
Expand Down
6 changes: 3 additions & 3 deletions docs/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ After installation is finished, you should be able to run the `neva` CLI from yo
neva version
```

It should emit something like `0.28.2`
It should emit something like `0.29.0`

### Hello, World!

Expand Down Expand Up @@ -254,7 +254,7 @@ This structure introduces two fundamental concepts in Nevalang: modules and pack
A module is a set of packages with a manifest file (`neva.yaml`). When we created our project with `neva new`, it generated a basic module with the following manifest file:

```yaml
neva: 0.28.2
neva: 0.29.0
```

This defines the Nevalang version for our project. As your project grows, you can include dependencies on third-party modules here.
Expand Down Expand Up @@ -413,7 +413,7 @@ When chaining nodes, we actually reference their ports implicitly. The chain cou
```neva
:start -> 'World' -> greet:data
greet:res -> println:data
println:sig -> :stop
println:res -> :stop
```

Both versions are equivalent, but the chained syntax is preferred for readability.
Expand Down
41 changes: 28 additions & 13 deletions e2e/99_bottles_verbose/main/main.neva
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,28 @@ import { fmt }

def Main(start any) (stop any) {
// we use explicit lock to implement fan-in to printNext2Lines
s Switch<int>, PrintNext2Lines, Lock<int>
s Switch<int>
print_next_2_lines PrintNext2Lines
lock Lock<int>
---
:start -> lock:sig
99 -> lock:data
[lock:data, s:else] -> printNext2Lines
printNext2Lines -> s:data
[lock:data, s:else] -> print_next_2_lines
print_next_2_lines -> s:data
-1 -> s:case[0] -> :stop
}

def PrintNext2Lines(n int) (n int) {
Dec<int>, PrintFirstLine, PrintSecondLine
dec Dec<int>
print_first_line PrintFirstLine
print_second_line PrintSecondLine
---
// printFirstLine and printSecondLine won't work in parallel
// print_first_line and print_second_line won't work in parallel
// because they are in the loop at the level of Main
:n -> printFirstLine:n
printFirstLine:n -> dec:data
dec:res -> printSecondLine:n
printSecondLine:n -> :n
:n -> print_first_line:n
print_first_line:n -> dec:data
dec:res -> print_second_line:n
print_second_line:n -> :n
}

// === First Line ===
Expand All @@ -31,7 +35,12 @@ const firstLine2 string = '1 bottle of beer on the wall, 1 bottle of beer.'
const firstLine3 string = 'No more bottles of beer on the wall, no more bottles of beer.'

def PrintFirstLine(n int) (n int) {
s Switch<int>, p1 fmt.Println, p2 fmt.Println, fmt.Printf, Lock<int>, Panic
s Switch<int>
p1 fmt.Println
p2 fmt.Println
printf fmt.Printf
lock Lock<int>
panic Panic
---
:n -> [s:data, lock:data]

Expand All @@ -45,7 +54,7 @@ def PrintFirstLine(n int) (n int) {
$firstLine1 -> printf:tpl
]

[p1:sig, p2:sig, printf:sig] -> lock:sig
[p1:res, p2:res, printf:sig] -> lock:sig
printf:err -> panic
lock:data -> :n
}
Expand All @@ -58,7 +67,13 @@ const secondLine3 string = 'Take one down and pass it around, no more bottles of
const secondLine4 string = 'Go to the store and buy some more, 99 bottles of beer on the wall.'

def PrintSecondLine(n int) (n int) {
s Switch<int>, p1 fmt.Println, p2 fmt.Println, p3 fmt.Println, fmt.Printf, Lock<int>, Panic
s Switch<int>
p1 fmt.Println
p2 fmt.Println
p3 fmt.Println
printf fmt.Printf
lock Lock<int>
panic Panic
---
:n -> [s:data, lock:data]

Expand All @@ -75,7 +90,7 @@ def PrintSecondLine(n int) (n int) {
$secondLine1 -> printf:tpl
]

[p1:sig, p2:sig, p3:sig, printf:sig] -> lock:sig
[p1:res, p2:res, p3:res, printf:sig] -> lock:sig
printf:err -> panic
lock:data -> :n
}
2 changes: 1 addition & 1 deletion e2e/99_bottles_verbose/neva.yml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
neva: 0.28.2
neva: 0.29.0
2 changes: 1 addition & 1 deletion e2e/add_nums_from_stdin_naive/main/main.neva
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ def Main(start any) (stop any) {
scanner2:res -> parser2:data
parser2:res -> add:right
add:res -> println:data
println:sig -> :stop
println:res -> :stop
[parser1:err, parser2:err] -> panic
}
2 changes: 1 addition & 1 deletion e2e/add_nums_from_stdin_naive/neva.yml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
neva: 0.28.2
neva: 0.29.0
Loading
Loading