From 20e64dcf839f495b40644c37bfca5e41ad0c5740 Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Fri, 6 Dec 2024 14:21:23 +0500 Subject: [PATCH 01/28] refactor(sourcecode): node.Deps -> node.DIArgs --- internal/compiler/analyzer/nodes.go | 10 ++++---- internal/compiler/desugarer/node.go | 10 ++++---- internal/compiler/parser/listener_helpers.go | 3 +-- internal/compiler/sourcecode/sourcecode.go | 2 +- internal/runtime/funcs/time_delay.go | 4 ++-- std/builtin/streams.neva | 24 ++++---------------- std/time/time.neva | 2 +- 7 files changed, 19 insertions(+), 36 deletions(-) diff --git a/internal/compiler/analyzer/nodes.go b/internal/compiler/analyzer/nodes.go index e0c9d109..a52f9329 100644 --- a/internal/compiler/analyzer/nodes.go +++ b/internal/compiler/analyzer/nodes.go @@ -171,7 +171,7 @@ func (a Analyzer) analyzeNode( } } - if node.Deps == nil { + if node.DIArgs == nil { return src.Node{ Directives: node.Directives, EntityRef: node.EntityRef, @@ -188,8 +188,8 @@ func (a Analyzer) analyzeNode( // implement interface->component subtyping // in a way where FP possible - resolvedFlowDI := make(map[string]src.Node, len(node.Deps)) - for depName, depNode := range node.Deps { + resolvedFlowDI := make(map[string]src.Node, len(node.DIArgs)) + for depName, depNode := range node.DIArgs { resolvedDep, _, err := a.analyzeNode( compIface, depNode, @@ -208,7 +208,7 @@ func (a Analyzer) analyzeNode( Directives: node.Directives, EntityRef: node.EntityRef, TypeArgs: resolvedNodeArgs, - Deps: resolvedFlowDI, + DIArgs: resolvedFlowDI, Meta: node.Meta, ErrGuard: node.ErrGuard, }, foundInterface{ @@ -235,7 +235,7 @@ func (a Analyzer) getNodeInterface( } } - if node.Deps != nil { + if node.DIArgs != nil { return src.Interface{}, &compiler.Error{ Message: "Only component node can have dependency injection", Location: &location, diff --git a/internal/compiler/desugarer/node.go b/internal/compiler/desugarer/node.go index 439ada31..8d082a18 100644 --- a/internal/compiler/desugarer/node.go +++ b/internal/compiler/desugarer/node.go @@ -56,14 +56,14 @@ func (Desugarer) handleNode( Directives[compiler.AutoportsDirective] // nothing to desugar - if !hasAutoports && len(node.Deps) != 1 { + if !hasAutoports && len(node.DIArgs) != 1 { desugaredNodes[nodeName] = node return extraConnections, nil } // --- anon dep --- - depArg, ok := node.Deps[""] + depArg, ok := node.DIArgs[""] if ok { for depParamName, depParam := range entity.Component.Nodes { depEntity, _, err := scope.Entity(depParam.EntityRef) @@ -71,13 +71,13 @@ func (Desugarer) handleNode( panic(err) } if depEntity.Kind == src.InterfaceEntity { - desugaredDeps := maps.Clone(node.Deps) + desugaredDeps := maps.Clone(node.DIArgs) desugaredDeps[depParamName] = depArg node = src.Node{ Directives: node.Directives, EntityRef: node.EntityRef, TypeArgs: node.TypeArgs, - Deps: desugaredDeps, + DIArgs: desugaredDeps, Meta: node.Meta, } break @@ -127,7 +127,7 @@ func (Desugarer) handleNode( }, Directives: node.Directives, TypeArgs: node.TypeArgs, - Deps: node.Deps, + DIArgs: node.DIArgs, Meta: node.Meta, } diff --git a/internal/compiler/parser/listener_helpers.go b/internal/compiler/parser/listener_helpers.go index aed5c45a..ac740d13 100644 --- a/internal/compiler/parser/listener_helpers.go +++ b/internal/compiler/parser/listener_helpers.go @@ -502,7 +502,7 @@ func parseNodes( EntityRef: parsedRef, TypeArgs: typeArgs, ErrGuard: errGuard, - Deps: deps, + DIArgs: deps, Meta: core.Meta{ Text: node.GetText(), Start: core.Position{ @@ -1159,4 +1159,3 @@ func parseCompDef(actx generated.ICompDefContext) (src.Entity, *compiler.Error) }, }, nil } - diff --git a/internal/compiler/sourcecode/sourcecode.go b/internal/compiler/sourcecode/sourcecode.go index 051c0a68..0f5b56aa 100644 --- a/internal/compiler/sourcecode/sourcecode.go +++ b/internal/compiler/sourcecode/sourcecode.go @@ -184,7 +184,7 @@ type Node struct { EntityRef core.EntityRef `json:"entityRef,omitempty"` TypeArgs TypeArgs `json:"typeArgs,omitempty"` ErrGuard bool `json:"errGuard,omitempty"` // ErrGuard explains if node is used with `?` operator. - Deps map[string]Node `json:"flowDi,omitempty"` // Dependency Injection. + DIArgs map[string]Node `json:"diArgs,omitempty"` // Dependency Injection. Meta core.Meta `json:"meta,omitempty"` } diff --git a/internal/runtime/funcs/time_delay.go b/internal/runtime/funcs/time_delay.go index 022749b7..0a6bd8d8 100644 --- a/internal/runtime/funcs/time_delay.go +++ b/internal/runtime/funcs/time_delay.go @@ -20,7 +20,7 @@ func (timeDelay) Create(io runtime.IO, _ runtime.Msg) (func(ctx context.Context) return nil, err } - dataOut, err := io.Out.Single("data") + resOut, err := io.Out.Single("res") if err != nil { return nil, err } @@ -39,7 +39,7 @@ func (timeDelay) Create(io runtime.IO, _ runtime.Msg) (func(ctx context.Context) time.Sleep(time.Duration(durMsg.Int())) - if !dataOut.Send(ctx, dataMsg) { + if !resOut.Send(ctx, dataMsg) { return } } diff --git a/std/builtin/streams.neva b/std/builtin/streams.neva index afb5abc8..024fd4d8 100644 --- a/std/builtin/streams.neva +++ b/std/builtin/streams.neva @@ -2,7 +2,7 @@ // Wait blocks until last stream item arrive, then sends a signal. pub def Wait(data stream) (sig any) { - Del + del Del --- :data -> .last -> switch { true -> :sig @@ -26,22 +26,6 @@ pub interface IPortReducer(data stream) (res T) // IWhileHandler is a dependency for While. pub interface IWhileHandler(data T) (res T, err error) -// While implements truly sequential loop. -// dependency node won't receive next data until it sends a result. -// Sometimes it's crucial to guarantee this, to avoid race conditions. -// E.g. you have pipeline of nodes that produce side-effects and order matters. -// You can wrap them in single handler and safely pass to `While`. -// `While` is basically just a shortcut for manually looped network topology. -// -pub def While(from T, to T) (sig any, err error) { - handler IWhileHandler? - --- - [:from, handler] -> switch { - :to -> :sig - _ -> handler - } -} - // These constants are used for binding by Field. const dataPath list = ['data'] const lastPath list = ['last'] @@ -52,11 +36,11 @@ const idxPath list = ['idx'] // IMapHandler is a dependency for Map. pub interface IMapHandler(data T) (res Y) +// TODO map is not concurrency safe like For // Map maps one stream onto another. // Just like For, it does not block the stream. As soon as one item processed, // it sends an item downstream and processes the next one. -// It's not recommented but possible to also produce side-effects. -// But, if all you need is side-effects, use For instead. +// It's possible but not recommended to produce side-effects. pub def Map(data stream) (res stream) { fanOut FanOut> handler IMapHandler @@ -146,7 +130,7 @@ pub def Accumulator(init T, upd T, last bool) (cur T, res T) // --- For --- // `For` applies a handler to each item in a stream to produce side-effects. -// It never modifies the stream - use `Map/Filter/Reduce` for transformations. +// It never modifies the stream. // // It uses back pressure to ensure the handler processes items sequentially - // the next item is not sent until the handler signals completion of the previous one. diff --git a/std/time/time.neva b/std/time/time.neva index 300f5d8a..aa1060c5 100644 --- a/std/time/time.neva +++ b/std/time/time.neva @@ -20,4 +20,4 @@ pub def After(dur Duration) (sig) // When enough time has passed, it sends a data to its output port. // If all you need is just block the flow, use Sleep instead. #extern(time_delay) -pub def Delay(dur Duration, data T) (data T) \ No newline at end of file +pub def Delay(dur Duration, data T) (res T) \ No newline at end of file From 58bdfa01b6efa96972b114166349aae93e125876 Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Fri, 6 Dec 2024 14:26:12 +0500 Subject: [PATCH 02/28] fix(compiler:irgen): deps drill (passing handlers through components) --- internal/compiler/irgen/irgen.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/internal/compiler/irgen/irgen.go b/internal/compiler/irgen/irgen.go index 9dbecfa7..2b424fcf 100644 --- a/internal/compiler/irgen/irgen.go +++ b/internal/compiler/irgen/irgen.go @@ -151,6 +151,23 @@ func (g Generator) processNode( } } + // TODO e2e test + // sometimes DI nodes are drilled down + // example: `handler Pass{handler IHandler}` + // our component is used like this `Parent{handler FilterOdd}` + // Parent.handler is not interface, but its component has interface + // It needs our DI nodes, so we merge our DI with node's DI + if len(nodeCtx.node.DIArgs) > 0 { + if node.DIArgs == nil { + node.DIArgs = make(map[string]src.Node) + } + for k, ourDIarg := range nodeCtx.node.DIArgs { + if _, exists := node.DIArgs[k]; !exists { + node.DIArgs[k] = ourDIarg + } + } + } + subNodeCtx := nodeContext{ path: append(nodeCtx.path, nodeName), portsUsage: nodePortsUsage, @@ -158,7 +175,7 @@ func (g Generator) processNode( } var scopeToUse src.Scope - if injectedNode, isDINode := nodeCtx.node.Deps[nodeName]; isDINode { + if injectedNode, isDINode := nodeCtx.node.DIArgs[nodeName]; isDINode { subNodeCtx.node = injectedNode scopeToUse = scope } else { From e7408b344138282f153764177cabeedba9cd9a24 Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Sat, 7 Dec 2024 04:44:15 +0500 Subject: [PATCH 03/28] feat(std): anonymous single ports in interfaces; re-implemented filter; refactor(std): names, ports; --- .vscode/launch.json | 4 +- cmd/lsp/server/server.go | 2 +- docs/book/directives.md | 2 +- docs/tutorial.md | 2 +- examples/map_list/main.neva | 10 ++-- examples/stream_to_list/main.neva | 5 +- pkg/version.go | 2 +- std/builtin/collections.neva | 2 +- std/builtin/core.neva | 8 +-- std/builtin/routers.neva | 11 +--- std/builtin/streams.neva | 92 ++++++++++++------------------- std/fmt/fmt.neva | 13 ++--- std/streams/streams.neva | 3 - std/time/time.neva | 2 +- 14 files changed, 60 insertions(+), 98 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index a530a0f8..c9612828 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,8 +7,8 @@ "request": "launch", "mode": "auto", "program": "${workspaceFolder}/cmd/neva", - "cwd": "${workspaceFolder}/e2e", - "args": ["run", "--trace", "tutorial/src"] + "cwd": "${workspaceFolder}/examples", + "args": ["run", "--trace", "filter_list"] }, { "name": "DEBUG CODEGEN", diff --git a/cmd/lsp/server/server.go b/cmd/lsp/server/server.go index 664f99cf..e949b3fe 100644 --- a/cmd/lsp/server/server.go +++ b/cmd/lsp/server/server.go @@ -60,7 +60,7 @@ 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, err.Meta.Location.String()) s.problemFiles[uri] = struct{}{} notify( protocol.ServerTextDocumentPublishDiagnostics, diff --git a/docs/book/directives.md b/docs/book/directives.md index 5f853c01..76d4b2fd 100644 --- a/docs/book/directives.md +++ b/docs/book/directives.md @@ -36,7 +36,7 @@ def Main(start any) (stop any) { :start -> lock:sig greeting:msg -> lock:data lock:data -> println:data - println:sig -> :stop + println:res -> :stop } ``` diff --git a/docs/tutorial.md b/docs/tutorial.md index aca40405..156b8aca 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -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. diff --git a/examples/map_list/main.neva b/examples/map_list/main.neva index d6f198e0..d5125186 100644 --- a/examples/map_list/main.neva +++ b/examples/map_list/main.neva @@ -3,10 +3,10 @@ import { lists, fmt } const lst list = [50, 30, 20, 100] def Main(start any) (stop any) { - ListToStream - Map{Dec} - List - fmt.Println + s2l StreamToList + map Map{Dec} + println fmt.Println + l2s ListToStream --- - :start -> $lst -> listToStream -> map -> list -> println -> :stop + :start -> $lst -> l2s -> map -> s2l -> println -> :stop } diff --git a/examples/stream_to_list/main.neva b/examples/stream_to_list/main.neva index 4785c569..700f2dbf 100644 --- a/examples/stream_to_list/main.neva +++ b/examples/stream_to_list/main.neva @@ -1,7 +1,8 @@ import { fmt } def Main(start any) (stop any) { - List, fmt.Println + s2l StreamToList + println fmt.Println --- - :start -> 1..11 -> list -> println -> :stop + :start -> 1..11 -> s2l -> println -> :stop } diff --git a/pkg/version.go b/pkg/version.go index e482c5ba..2d93ae59 100644 --- a/pkg/version.go +++ b/pkg/version.go @@ -2,4 +2,4 @@ package pkg // Version is the current version of the language and stdlib. // Don't forget to update it before release new tag. -var Version = "0.28.2" //nolint:gochecknoglobals +var Version = "0.29.0" //nolint:gochecknoglobals diff --git a/std/builtin/collections.neva b/std/builtin/collections.neva index 0971cdf7..e8c6eea1 100644 --- a/std/builtin/collections.neva +++ b/std/builtin/collections.neva @@ -7,7 +7,7 @@ pub def Len | dict | string>(data T) (res int) // List receives stream and sends list with all elements from the stream. #extern(stream_to_list) -pub def List(data stream) (res list) +pub def StreamToList(data stream) (res list) // Push creates new list with appended element. #extern(list_push) diff --git a/std/builtin/core.neva b/std/builtin/core.neva index 0f232d2e..7b47c424 100644 --- a/std/builtin/core.neva +++ b/std/builtin/core.neva @@ -55,10 +55,6 @@ pub def Pass(data T) (res T) { :data -> :res } -// TODO add err outport -pub interface ITapHandler(data T) (sig any) - -// TODO add err outport // Sometimes component needs to receive data, perform some action and pass that // data further. However, due to impossibility to reuse same sender twice or // more, it leads to need for explicit locks. Deferred connections do not cover @@ -69,10 +65,12 @@ pub interface ITapHandler(data T) (sig any) // dealing with locks manually. Handler can send error, in that case `Tap` will // propogate it up to parent node. pub def Tap(data T) (res T) { - Lock + lock Lock handler ITapHandler --- :data -> [handler, lock:data] handler -> lock:sig lock -> :res } + +pub interface ITapHandler(T) (any) diff --git a/std/builtin/routers.neva b/std/builtin/routers.neva index 0f2cdbae..bb7842d6 100644 --- a/std/builtin/routers.neva +++ b/std/builtin/routers.neva @@ -21,13 +21,4 @@ pub def FanOut(data T) ([data] T) // FanIn merges several sources of data into single one. // It makes sure order of incoming messages is respected. #extern(fan_in) -pub def FanIn([data] T) (res T) - -// IDEA: there's another variation of Select/Switch -// (data T, [if] any) ([then] T, else T) -// it's like a mix between Switch and Select -// - it's like a switch, but it cares where data came from, not what data is -// - it's like a select, but it cares where to send data, not what to send - -// MatchSwitch maps and routes the data. -// pub def MatchSwitch(data T, [if] T, [then] T, else T) ([then] T, else T) +pub def FanIn([data] T) (res T) \ No newline at end of file diff --git a/std/builtin/streams.neva b/std/builtin/streams.neva index 024fd4d8..9e6019f7 100644 --- a/std/builtin/streams.neva +++ b/std/builtin/streams.neva @@ -17,15 +17,10 @@ pub def ArrPortToStream([port] T) (data stream) // IPortReducer reduces a stream of messages to one single message. // It's expected to send a result message after every processed stream. -pub interface IPortReducer(data stream) (res T) +pub interface IPortReducer(stream) (T) // === Iterators === -// --- While --- - -// IWhileHandler is a dependency for While. -pub interface IWhileHandler(data T) (res T, err error) - // These constants are used for binding by Field. const dataPath list = ['data'] const lastPath list = ['last'] @@ -34,7 +29,7 @@ const idxPath list = ['idx'] // --- Map --- // IMapHandler is a dependency for Map. -pub interface IMapHandler(data T) (res Y) +pub interface IMapHandler(T) (Y) // TODO map is not concurrency safe like For // Map maps one stream onto another. @@ -59,69 +54,51 @@ pub def Map(data stream) (res stream) { // --- Filter --- -// IFilterHandler is a dependency for Filter component. -// pub interface IFilterHandler(data T) (res bool) - -// TODO: https://github.com/nevalang/neva/issues/763 -// Filter is for filtering items in a stream, -// producing a new stream with only items that passed the filter. -// -// Unlike other iterators, it blocks the incoming stream, -// before creating outgoing one. This is needed to handle metadata correctly. -// -// Output items may have different indexes than corresponding input ones. -// For example: filtering even numbers from [1, 2, 3] will emit 2 with index 0. -// This also affects which item is marked as last - 2 will be marked as last. -// -// This is important if you need to manually handle stream metadata, -// though it's generally better to avoid doing so. -// pub def Filter(data stream) (res stream) { -// Cond> -// FanOut> -// handler IFilterHandler +pub def Filter(data stream) (res stream) { + split Split{IPredicate} + s2l StreamToList + l2s ListToStream + --- + :data -> split + split:then -> s2l -> l2s -> :res +} -// --- +pub def Split(data stream) (then stream, else stream) { + cond Cond> + predicate IPredicate + --- + :data -> [cond:data, predicate] + predicate -> cond:if + cond:then -> :then + cond:else -> :else +} -// :data -> fanOut - -// fanOut[0] -> cond:data -// fanOut[1] -> .data -> handler -> cond:if - -// cond:then -> :res -// } +pub interface IPredicate(T) (bool) // --- Reduce --- -// IReduceHandler is a dependency for Reduce. -pub interface IReduceHandler(left T, right T) (res Y) +// IReducer is a dependency for Reduce. +pub interface IReducer(left T, right T) (res Y) // Reduce applies a reduction component to a stream of messages, accumulating the result. // It takes an initial value and a stream of data, and produces a single result. pub def Reduce(data stream, init Y) (res Y) { - handler IReduceHandler - fanOut FanOut> + reducer IReducer acc Accumulator - --- - :init -> acc:init - :data -> fanOut - fanOut[0] -> .data -> handler:right - fanOut[1] -> .last -> acc:last + :data -> [ + .data -> reducer:right, + .last -> acc:last + ] - acc:cur -> handler:left - handler -> acc:upd + acc:cur -> reducer:left + reducer -> acc:upd acc:res -> :res } -// IDEA: -// pub type AccumulatorUpdate strcut { -// data T -// last bool -// } - // Accumulator maintains the current state of the reduction. // It updates its value with each new input and outputs the final result when last is true. #extern(accumulator) @@ -142,7 +119,7 @@ pub def For(data stream) (res stream) { first First // to check if current msg is the first lock1 Lock> // to lock current msg before sending to handler lock2 Lock> // to lock current msg before sending downstream - handler IForEachHandler // to process current msg + handler ISideEffector // to process current msg pass1 Pass // to unlock current msg to send to handler pass2 Pass // to unlock current msg to send downstream --- @@ -157,14 +134,13 @@ pub def For(data stream) (res stream) { handler -> [pass1, pass2] } -// IForEachHandler is a dependency for For. -pub interface IForEachHandler(data T) (sig any) +pub interface ISideEffector(T) (any) // `First` is a helper that allows to check if given stream item is the first one. def First(data stream) (then stream, else stream) { - Cond> - Eq - Pass> + cond Cond> + eq Eq + pass Pass> --- :data -> [cond:data, pass] pass -> .idx -> eq:left diff --git a/std/fmt/fmt.neva b/std/fmt/fmt.neva index e9588bb6..900a5c25 100644 --- a/std/fmt/fmt.neva +++ b/std/fmt/fmt.neva @@ -1,17 +1,16 @@ -// TODO add err outport -// Println prints to the standard output with a newline. +// Println prints to stdout with newline and then sends message further. #extern(println) -pub def Println(data T) (sig struct{}) +pub def Println(data T) (res T) +// Print prints to stdout without newline and then sends message further. #extern(print) -pub def Print(data T) (sig struct{}) +pub def Print(data T) (res T) // Printf replaces `$` with the corresponding argument // and prints to the standard output. #extern(printf) -pub def Printf(tpl string, [args] any) (sig struct{}, err error) +pub def Printf(tpl string, [args] any) (sig any, err error) -// TODO add err outport -// Scanln scans text read from the standard input. +// Scanln scans text read from the standard input and then sends it further. #extern(scanln) pub def Scanln(sig any) (res string) \ No newline at end of file diff --git a/std/streams/streams.neva b/std/streams/streams.neva index 4b75eea2..d8aa4f04 100644 --- a/std/streams/streams.neva +++ b/std/streams/streams.neva @@ -23,6 +23,3 @@ pub type ProductResult struct { // elements from the second. #extern(stream_product) pub def Product(first stream, second stream) (data stream>) - -// TODO? -// pub def Uncons(data stream) (head T, tail stream) \ No newline at end of file diff --git a/std/time/time.neva b/std/time/time.neva index aa1060c5..36c3ad9a 100644 --- a/std/time/time.neva +++ b/std/time/time.neva @@ -12,7 +12,7 @@ pub const hour Duration = 3600000000000 // When enough time has passed, it sends a signal to its output port. // If you want to delay a message, use Delay instead. #extern(time_after) -pub def After(dur Duration) (sig) +pub def After(dur Duration) (sig any) // Delay waits for both dur and data messages. // As soon as they both arrive it starts waiting From 9ae995c613506f91d460b4b6c84d98c500e67bff Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Sat, 7 Dec 2024 04:46:27 +0500 Subject: [PATCH 04/28] feat(examples/e2e): return filter test; add explicit any to ports; print(ln):sig -> :res --- e2e/add_nums_from_stdin_naive/main/main.neva | 2 +- .../main/main.neva | 6 ++-- .../main/main.neva | 2 +- .../main/main.neva | 6 ++-- .../main/main.neva | 4 +-- e2e/add_nums_verbose/main/main.neva | 2 +- e2e/comments/main/main.neva | 2 +- e2e/const_refs_verbose/main/main.neva | 2 +- e2e/duplicate_receiver/e2e_test.go | 2 +- e2e/duplicate_sender/main/main.neva | 2 +- e2e/echo_verbose/main/main.neva | 4 +-- e2e/enums_verbose/main/main.neva | 4 +-- e2e/hello_world_verbose/main/main.neva | 2 +- .../main/main.neva | 2 +- .../main/main.neva | 2 +- .../main/main.neva | 2 +- .../main/main.neva | 2 +- .../main/main.neva | 2 +- e2e/list_with_neg_nums/main/main.neva | 2 +- e2e/map_list_verbose/main/main.neva | 10 +++---- e2e/print_float/main/main.neva | 2 +- e2e/regex_submatch_verbose/main/main.neva | 2 +- e2e/struct_builder_verbose/main/main.neva | 2 +- e2e/struct_builder_with_sugar/main/main.neva | 2 +- .../main/main.neva | 2 +- e2e/struct_selector_verbose/main/main.neva | 2 +- .../main/main.neva | 2 +- e2e/struct_selector_with_sugar/main/main.neva | 4 +-- examples/add_numbers_from_stdin/main.neva | 4 +-- examples/advanced_error_handling/main.neva | 2 +- examples/enums/main.neva | 2 +- examples/filter_list/e2e_test.go | 3 -- examples/filter_list/main.neva | 29 +++++++++---------- examples/map_list/main.neva | 10 +++---- examples/struct_selector/main.neva | 2 +- 35 files changed, 63 insertions(+), 69 deletions(-) diff --git a/e2e/add_nums_from_stdin_naive/main/main.neva b/e2e/add_nums_from_stdin_naive/main/main.neva index c3a59dfc..2ccac3bc 100644 --- a/e2e/add_nums_from_stdin_naive/main/main.neva +++ b/e2e/add_nums_from_stdin_naive/main/main.neva @@ -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 } diff --git a/e2e/add_nums_from_stdin_with_default_any/main/main.neva b/e2e/add_nums_from_stdin_with_default_any/main/main.neva index 8ba3b843..c67f0fac 100644 --- a/e2e/add_nums_from_stdin_with_default_any/main/main.neva +++ b/e2e/add_nums_from_stdin_with_default_any/main/main.neva @@ -5,10 +5,10 @@ def Main(start any) (stop any) { --- :start -> aux:sig [aux:res, aux:err] -> println:data - println:sig -> :stop + println:res -> :stop } -def Aux(sig) (res int, err error) { +def Aux(sig any) (res int, err error) { reader1 IntReader reader2 IntReader add Add @@ -23,7 +23,7 @@ def Aux(sig) (res int, err error) { def IntReader(sig any) (num int, err error) { fmt.Scanln, strconv.ParseNum --- - :sig -> scanln:sig + :sig -> scanln:res scanln:res -> parseNum:data parseNum:res -> :num parseNum:err -> :err diff --git a/e2e/add_nums_from_stdin_with_err_handling/main/main.neva b/e2e/add_nums_from_stdin_with_err_handling/main/main.neva index e1d1bcea..a18e8f96 100644 --- a/e2e/add_nums_from_stdin_with_err_handling/main/main.neva +++ b/e2e/add_nums_from_stdin_with_err_handling/main/main.neva @@ -13,6 +13,6 @@ def Main(start any) (stop any) { parser1:res -> [add:left, scanner2:sig] scanner2:res -> parser2:data parser2:res -> add:right - println:sig -> :stop + println:res -> :stop [parser1:err, parser2:err, add:res] -> println:data } diff --git a/e2e/add_nums_from_stdin_with_multuple_senders/main/main.neva b/e2e/add_nums_from_stdin_with_multuple_senders/main/main.neva index ca13205e..2a3f01c1 100644 --- a/e2e/add_nums_from_stdin_with_multuple_senders/main/main.neva +++ b/e2e/add_nums_from_stdin_with_multuple_senders/main/main.neva @@ -5,10 +5,10 @@ def Main(start any) (stop any) { --- :start -> aux:sig [aux:res, aux:err] -> println:data - println:sig -> :stop + println:res -> :stop } -def Aux(sig) (res int, err error) { +def Aux(sig any) (res int, err error) { reader1 IntReader reader2 IntReader add Add @@ -23,7 +23,7 @@ def Aux(sig) (res int, err error) { def IntReader(sig any) (num int, err error) { fmt.Scanln, strconv.ParseNum --- - :sig -> scanln:sig + :sig -> scanln:res scanln:res -> parseNum:data parseNum:res -> :num parseNum:err -> :err diff --git a/e2e/add_nums_from_stdin_with_sub_components/main/main.neva b/e2e/add_nums_from_stdin_with_sub_components/main/main.neva index f1db12c1..dbf91ccf 100644 --- a/e2e/add_nums_from_stdin_with_sub_components/main/main.neva +++ b/e2e/add_nums_from_stdin_with_sub_components/main/main.neva @@ -5,7 +5,7 @@ def Main(start any) (stop any) { --- :start -> aux:sig [aux:res, aux:err] -> println:data - println:sig -> :stop + println:res -> :stop } def Aux(sig any) (res int, err error) { @@ -23,7 +23,7 @@ def Aux(sig any) (res int, err error) { def IntReader(sig any) (num int, err error) { fmt.Scanln, strconv.ParseNum --- - :sig -> scanln:sig + :sig -> scanln:res scanln:res -> parseNum:data parseNum:res -> :num parseNum:err -> :err diff --git a/e2e/add_nums_verbose/main/main.neva b/e2e/add_nums_verbose/main/main.neva index 151be4a7..6789cd43 100644 --- a/e2e/add_nums_verbose/main/main.neva +++ b/e2e/add_nums_verbose/main/main.neva @@ -9,5 +9,5 @@ def Main(start any) (stop any) { 2 -> adder:right ] adder:res -> println:data - println:sig -> :stop + println:res -> :stop } \ No newline at end of file diff --git a/e2e/comments/main/main.neva b/e2e/comments/main/main.neva index 5ed083fe..b0632dd7 100644 --- a/e2e/comments/main/main.neva +++ b/e2e/comments/main/main.neva @@ -9,7 +9,7 @@ def Main(start any) (stop any) { --- // comment inside def 2 :start -> println:data - println:sig -> :stop + println:res -> :stop // comment inside def 3 } // top-level comment 2 \ No newline at end of file diff --git a/e2e/const_refs_verbose/main/main.neva b/e2e/const_refs_verbose/main/main.neva index 16ad3f7b..48ca25ab 100644 --- a/e2e/const_refs_verbose/main/main.neva +++ b/e2e/const_refs_verbose/main/main.neva @@ -19,5 +19,5 @@ def Main(start any) (stop any) { fmt.Println --- :start -> $numsStruct -> println:data - println:sig -> :stop + println:res -> :stop } diff --git a/e2e/duplicate_receiver/e2e_test.go b/e2e/duplicate_receiver/e2e_test.go index 3414fda6..885a211e 100644 --- a/e2e/duplicate_receiver/e2e_test.go +++ b/e2e/duplicate_receiver/e2e_test.go @@ -18,7 +18,7 @@ func Test(t *testing.T) { require.Contains( t, string(out), - "main/main.neva:7:1: port 'println:sig' is used twice\n", + "main/main.neva:7:1: port 'println:res' is used twice\n", ) require.Equal(t, 0, cmd.ProcessState.ExitCode()) diff --git a/e2e/duplicate_sender/main/main.neva b/e2e/duplicate_sender/main/main.neva index 17e71196..8a3cf57b 100644 --- a/e2e/duplicate_sender/main/main.neva +++ b/e2e/duplicate_sender/main/main.neva @@ -5,5 +5,5 @@ def Main(start any) (stop any) { --- :start -> println :start -> panic - println:sig -> :stop + println:res -> :stop } \ No newline at end of file diff --git a/e2e/echo_verbose/main/main.neva b/e2e/echo_verbose/main/main.neva index 97a818a8..e37ebd51 100644 --- a/e2e/echo_verbose/main/main.neva +++ b/e2e/echo_verbose/main/main.neva @@ -4,7 +4,7 @@ def Main(start any) (stop any) { fmt.Scanln fmt.Println --- - :start -> scanln:sig + :start -> scanln:res scanln:res -> println:data - println:sig -> :stop + println:res -> :stop } diff --git a/e2e/enums_verbose/main/main.neva b/e2e/enums_verbose/main/main.neva index cc0b8825..87e227cd 100644 --- a/e2e/enums_verbose/main/main.neva +++ b/e2e/enums_verbose/main/main.neva @@ -17,9 +17,9 @@ type Day enum { Sunday } -def DayPrinter(day Day) (sig) { +def DayPrinter(day Day) (sig any) { fmt.Println --- :day -> println:data - println:sig -> :sig + println:res -> :sig } \ No newline at end of file diff --git a/e2e/hello_world_verbose/main/main.neva b/e2e/hello_world_verbose/main/main.neva index 51a66f30..b90499cb 100644 --- a/e2e/hello_world_verbose/main/main.neva +++ b/e2e/hello_world_verbose/main/main.neva @@ -13,5 +13,5 @@ def Main(start any) (stop any) { :start -> lock:sig greeting:msg -> lock:data lock:data -> println:data - println:sig -> :stop + println:res -> :stop } \ No newline at end of file diff --git a/e2e/hello_world_with_const_sender/main/main.neva b/e2e/hello_world_with_const_sender/main/main.neva index 4d26a8bb..70a6fa3f 100644 --- a/e2e/hello_world_with_const_sender/main/main.neva +++ b/e2e/hello_world_with_const_sender/main/main.neva @@ -9,5 +9,5 @@ def Main(start any) (stop any) { :start -> lock:sig $greeting -> lock:data lock:data -> println:data - println:sig -> :stop + println:res -> :stop } \ No newline at end of file diff --git a/e2e/hello_world_with_implicit_any/main/main.neva b/e2e/hello_world_with_implicit_any/main/main.neva index 53d6b06b..4c0fa8a0 100644 --- a/e2e/hello_world_with_implicit_any/main/main.neva +++ b/e2e/hello_world_with_implicit_any/main/main.neva @@ -4,5 +4,5 @@ def Main(start any) (stop any) { fmt.Println --- :start -> 'Hello, World!' -> println:data - println:sig -> :stop + println:res -> :stop } \ No newline at end of file diff --git a/e2e/hello_world_with_literal_sender/main/main.neva b/e2e/hello_world_with_literal_sender/main/main.neva index f8fadbe4..5f7b7301 100644 --- a/e2e/hello_world_with_literal_sender/main/main.neva +++ b/e2e/hello_world_with_literal_sender/main/main.neva @@ -4,5 +4,5 @@ def Main(start any) (stop any) { println fmt.Println --- :start -> 'Hello, World!' -> println:data - println:sig -> :stop + println:res -> :stop } \ No newline at end of file diff --git a/e2e/hello_world_with_then_connection/main/main.neva b/e2e/hello_world_with_then_connection/main/main.neva index 18feee09..004daa61 100644 --- a/e2e/hello_world_with_then_connection/main/main.neva +++ b/e2e/hello_world_with_then_connection/main/main.neva @@ -6,5 +6,5 @@ def Main(start any) (stop any) { println fmt.Println --- :start -> $greeting -> println:data - println:sig -> :stop + println:res -> :stop } \ No newline at end of file diff --git a/e2e/hello_world_with_unnamed_node/main/main.neva b/e2e/hello_world_with_unnamed_node/main/main.neva index 81627177..fb154bf5 100644 --- a/e2e/hello_world_with_unnamed_node/main/main.neva +++ b/e2e/hello_world_with_unnamed_node/main/main.neva @@ -4,5 +4,5 @@ def Main(start any) (stop any) { fmt.Println --- :start -> 'Hello, World!' -> println:data - println:sig -> :stop + println:res -> :stop } \ No newline at end of file diff --git a/e2e/list_with_neg_nums/main/main.neva b/e2e/list_with_neg_nums/main/main.neva index a341ce61..0cfe78bb 100644 --- a/e2e/list_with_neg_nums/main/main.neva +++ b/e2e/list_with_neg_nums/main/main.neva @@ -6,5 +6,5 @@ def Main(start any) (stop any) { fmt.Println --- :start -> $l -> println:data - println:sig -> :stop + println:res -> :stop } \ No newline at end of file diff --git a/e2e/map_list_verbose/main/main.neva b/e2e/map_list_verbose/main/main.neva index 32708320..8229ec77 100644 --- a/e2e/map_list_verbose/main/main.neva +++ b/e2e/map_list_verbose/main/main.neva @@ -5,10 +5,10 @@ import { fmt } const lst list = [50, 30, 20, 100] def Main(start any) (stop any) { - Map{Dec} - List - fmt.Println - ListToStream + map_decr Map{Dec} + s2l StreamToList + println fmt.Println + l2s ListToStream --- - :start -> $lst -> listToStream -> map -> list -> println -> :stop + :start -> $lst -> l2s -> map_decr -> s2l -> println -> :stop } diff --git a/e2e/print_float/main/main.neva b/e2e/print_float/main/main.neva index 27b8631e..1ede436c 100644 --- a/e2e/print_float/main/main.neva +++ b/e2e/print_float/main/main.neva @@ -6,5 +6,5 @@ def Main(start any) (stop any) { fmt.Println --- :start -> $x -> println:data - println:sig -> :stop + println:res -> :stop } diff --git a/e2e/regex_submatch_verbose/main/main.neva b/e2e/regex_submatch_verbose/main/main.neva index 6a1f0db8..ef8056cf 100644 --- a/e2e/regex_submatch_verbose/main/main.neva +++ b/e2e/regex_submatch_verbose/main/main.neva @@ -8,6 +8,6 @@ def Main(start any) (stop any) { 'a(x*)b(y|z)c' -> submatch:regexp ] submatch:res -> println:data - println:sig -> :stop + println:res -> :stop submatch:err -> panic } diff --git a/e2e/struct_builder_verbose/main/main.neva b/e2e/struct_builder_verbose/main/main.neva index e35740c2..014539e0 100644 --- a/e2e/struct_builder_verbose/main/main.neva +++ b/e2e/struct_builder_verbose/main/main.neva @@ -18,5 +18,5 @@ def Main(start any) (stop any) { 32 -> builder:age ] builder:msg -> println:data - println:sig -> :stop + println:res -> :stop } \ No newline at end of file diff --git a/e2e/struct_builder_with_sugar/main/main.neva b/e2e/struct_builder_with_sugar/main/main.neva index a1de3e6f..e531ee74 100644 --- a/e2e/struct_builder_with_sugar/main/main.neva +++ b/e2e/struct_builder_with_sugar/main/main.neva @@ -14,5 +14,5 @@ def Main(start any) (stop any) { 32 -> builder:age ] builder:msg -> println:data - println:sig -> :stop + println:res -> :stop } \ No newline at end of file diff --git a/e2e/struct_selector_on_port_addr/main/main.neva b/e2e/struct_selector_on_port_addr/main/main.neva index 4123c3f7..9b5f9ee1 100644 --- a/e2e/struct_selector_on_port_addr/main/main.neva +++ b/e2e/struct_selector_on_port_addr/main/main.neva @@ -5,7 +5,7 @@ def Main(start any) (stop any) { --- :start -> foo:sig foo:msg -> .a -> println:data - println:sig -> :stop + println:res -> :stop } const s struct { a int } = { a: 42 } diff --git a/e2e/struct_selector_verbose/main/main.neva b/e2e/struct_selector_verbose/main/main.neva index cdc610d8..7d811897 100644 --- a/e2e/struct_selector_verbose/main/main.neva +++ b/e2e/struct_selector_verbose/main/main.neva @@ -29,5 +29,5 @@ def Main(start any) (stop any) { :start -> $user -> field:data field:res -> println:data - println:sig -> :stop + println:res -> :stop } diff --git a/e2e/struct_selector_with_more_sugar/main/main.neva b/e2e/struct_selector_with_more_sugar/main/main.neva index 2fd61105..71e73f78 100644 --- a/e2e/struct_selector_with_more_sugar/main/main.neva +++ b/e2e/struct_selector_with_more_sugar/main/main.neva @@ -22,6 +22,6 @@ const user User = { pet: { name: 'Charley' } } -def UserSender(sig) (u User) { +def UserSender(sig any) (u User) { :sig -> $user -> :u } diff --git a/e2e/struct_selector_with_sugar/main/main.neva b/e2e/struct_selector_with_sugar/main/main.neva index d73c9c21..68dc94b7 100644 --- a/e2e/struct_selector_with_sugar/main/main.neva +++ b/e2e/struct_selector_with_sugar/main/main.neva @@ -15,7 +15,7 @@ def Main(start any) (stop any) { --- :start -> userSender:sig userSender:u -> .pet.name -> println:data - println:sig -> :stop + println:res -> :stop } const user User = { @@ -23,6 +23,6 @@ const user User = { pet: { name: 'Charley' } } -def UserSender(sig) (u User) { +def UserSender(sig any) (u User) { :sig -> $user -> :u } diff --git a/examples/add_numbers_from_stdin/main.neva b/examples/add_numbers_from_stdin/main.neva index 3266a770..8e6e5d8d 100644 --- a/examples/add_numbers_from_stdin/main.neva +++ b/examples/add_numbers_from_stdin/main.neva @@ -7,7 +7,7 @@ def Main(start any) (stop any) { [app:res, app:err] -> println -> :stop } -def App(sig) (res int, err error) { +def App(sig any) (res int, err error) { readFirstInt ReadIntFromStdin readSecondInt ReadIntFromStdin add Add @@ -19,7 +19,7 @@ def App(sig) (res int, err error) { add -> :res } -def ReadIntFromStdin(sig) (num int, err error) { +def ReadIntFromStdin(sig any) (num int, err error) { fmt.Scanln, strconv.ParseNum --- :sig -> scanln -> parseNum diff --git a/examples/advanced_error_handling/main.neva b/examples/advanced_error_handling/main.neva index 7243900f..3b996625 100644 --- a/examples/advanced_error_handling/main.neva +++ b/examples/advanced_error_handling/main.neva @@ -8,7 +8,7 @@ def Main(start any) (stop any) { app:data -> println -> :stop } -def App(sig) (data string, err error) { +def App(sig any) (data string, err error) { http.Get? // '?' implicitly sends `:err` downstream --- :sig -> 'definitely not a valid URL' -> get diff --git a/examples/enums/main.neva b/examples/enums/main.neva index f71453af..32b71ac6 100644 --- a/examples/enums/main.neva +++ b/examples/enums/main.neva @@ -16,7 +16,7 @@ type Day enum { Sunday } -def PrintDay(day Day) (sig) { +def PrintDay(day Day) (sig any) { fmt.Println --- :day -> println -> :sig diff --git a/examples/filter_list/e2e_test.go b/examples/filter_list/e2e_test.go index 6909a5ad..b18adc9b 100644 --- a/examples/filter_list/e2e_test.go +++ b/examples/filter_list/e2e_test.go @@ -11,9 +11,6 @@ import ( ) func Test(t *testing.T) { - // TODO: https://github.com/nevalang/neva/issues/763 - t.Skip("Filter is not implemented yet") - err := os.Chdir("..") require.NoError(t, err) diff --git a/examples/filter_list/main.neva b/examples/filter_list/main.neva index 06f779fe..80cd1ff9 100644 --- a/examples/filter_list/main.neva +++ b/examples/filter_list/main.neva @@ -1,19 +1,16 @@ -// TODO: https://github.com/nevalang/neva/issues/763 -// import { fmt } +import { fmt } -// const lst list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +const lst list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -// def Main(start any) (stop any) { -// ListToStream -// Filter{Even} -// For{fmt.Println} -// Wait -// --- -// :start -> { -// $lst -> listToStream -> filter -> for -> wait -> :stop -// } -// } +def Main(start any) (stop any) { + l2s ListToStream + filter_even Filter{Even} + for_print For{fmt.Println} + wait Wait + --- + :start -> $lst -> l2s -> filter_even -> for_print -> wait -> :stop +} -// def Even(data int) (res bool) { -// ((:data % 2) == 0) -> :res -// } +def Even(data int) (res bool) { + ((:data % 2) == 0) -> :res +} diff --git a/examples/map_list/main.neva b/examples/map_list/main.neva index d5125186..2ea6842a 100644 --- a/examples/map_list/main.neva +++ b/examples/map_list/main.neva @@ -3,10 +3,10 @@ import { lists, fmt } const lst list = [50, 30, 20, 100] def Main(start any) (stop any) { - s2l StreamToList - map Map{Dec} - println fmt.Println - l2s ListToStream + s2l StreamToList + map_dec Map{Dec} + println fmt.Println> + l2s ListToStream --- - :start -> $lst -> l2s -> map -> s2l -> println -> :stop + :start -> $lst -> l2s -> map_dec -> s2l -> println -> :stop } diff --git a/examples/struct_selector/main.neva b/examples/struct_selector/main.neva index fa663dec..b5216e5d 100644 --- a/examples/struct_selector/main.neva +++ b/examples/struct_selector/main.neva @@ -18,6 +18,6 @@ const user User = { pet: { name: 'Charley' } } -def GetUser(sig) (u User) { +def GetUser(sig any) (u User) { :sig -> $user -> :u } From 49a03e9de0ea58b9c269b81db1c837d9b70a70b4 Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Sat, 7 Dec 2024 04:47:40 +0500 Subject: [PATCH 05/28] fix(builder): refs to core.Meta --- internal/builder/builder.go | 9 +++++---- internal/builder/get.go | 6 +++--- internal/builder/git.go | 5 ++--- internal/builder/q.go | 10 +++++----- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/internal/builder/builder.go b/internal/builder/builder.go index 2f14b42c..e2377854 100644 --- a/internal/builder/builder.go +++ b/internal/builder/builder.go @@ -8,6 +8,7 @@ import ( "github.com/nevalang/neva/internal/compiler" src "github.com/nevalang/neva/internal/compiler/sourcecode" + "github.com/nevalang/neva/internal/compiler/sourcecode/core" "github.com/nevalang/neva/pkg" "github.com/nevalang/neva/std" ) @@ -35,14 +36,14 @@ func (b Builder) Build( } // inject stdlib dep to entry module - stdModRef := src.ModuleRef{ + stdModRef := core.ModuleRef{ Path: "std", Version: pkg.Version, } entryMod.Manifest.Deps["std"] = stdModRef // inject entry mod into the build - mods := map[src.ModuleRef]compiler.RawModule{ + mods := map[core.ModuleRef]compiler.RawModule{ {Path: "@"}: entryMod, } @@ -89,7 +90,7 @@ func (b Builder) Build( } // inject stdlib dep into every downloaded dep mod - depMod.Manifest.Deps["std"] = src.ModuleRef{ + depMod.Manifest.Deps["std"] = core.ModuleRef{ Path: "std", Version: pkg.Version, } @@ -100,7 +101,7 @@ func (b Builder) Build( } return compiler.RawBuild{ - EntryModRef: src.ModuleRef{Path: "@"}, + EntryModRef: core.ModuleRef{Path: "@"}, Modules: mods, }, entryModRootPath, nil } diff --git a/internal/builder/get.go b/internal/builder/get.go index 19222259..5ba68631 100644 --- a/internal/builder/get.go +++ b/internal/builder/get.go @@ -4,11 +4,11 @@ import ( "errors" "fmt" - src "github.com/nevalang/neva/internal/compiler/sourcecode" + "github.com/nevalang/neva/internal/compiler/sourcecode/core" ) func (b Builder) Get(wd, path, version string) (string, error) { - ref := src.ModuleRef{ + ref := core.ModuleRef{ Path: path, Version: version, } @@ -36,7 +36,7 @@ func (b Builder) Get(wd, path, version string) (string, error) { ) } - manifest.Deps[path] = src.ModuleRef{ + manifest.Deps[path] = core.ModuleRef{ Path: path, Version: actualVersion, } diff --git a/internal/builder/git.go b/internal/builder/git.go index 29c0a578..b4d75a27 100644 --- a/internal/builder/git.go +++ b/internal/builder/git.go @@ -7,13 +7,12 @@ import ( git "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" - - "github.com/nevalang/neva/internal/compiler/sourcecode" + "github.com/nevalang/neva/internal/compiler/sourcecode/core" ) // downloadDep returns path where it downloaded dependency // and its downloaded version in case version wasn't specified. -func (p Builder) downloadDep(depModRef sourcecode.ModuleRef) (string, string, error) { +func (p Builder) downloadDep(depModRef core.ModuleRef) (string, string, error) { fsPath := fmt.Sprintf( "%s/%s_%s", p.thirdPartyPath, diff --git a/internal/builder/q.go b/internal/builder/q.go index ac750513..6229c2bd 100644 --- a/internal/builder/q.go +++ b/internal/builder/q.go @@ -1,16 +1,16 @@ package builder -import src "github.com/nevalang/neva/internal/compiler/sourcecode" +import "github.com/nevalang/neva/internal/compiler/sourcecode/core" -type queue []src.ModuleRef +type queue []core.ModuleRef -func (q *queue) enqueue(deps map[string]src.ModuleRef) { +func (q *queue) enqueue(deps map[string]core.ModuleRef) { for _, dep := range deps { *q = append(*q, dep) } } -func (q *queue) dequeue() src.ModuleRef { +func (q *queue) dequeue() core.ModuleRef { tmp := *q last := (tmp)[len(tmp)-1] *q = (tmp)[:len(tmp)-1] @@ -21,7 +21,7 @@ func (q *queue) empty() bool { return len(*q) == 0 } -func newQueue(deps map[string]src.ModuleRef) *queue { +func newQueue(deps map[string]core.ModuleRef) *queue { q := make(queue, 0, len(deps)) q.enqueue(deps) return &q From 4fc2901c6485238ec3f4fdff22e2ef4ebd571386 Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Sat, 7 Dec 2024 04:47:54 +0500 Subject: [PATCH 06/28] fix(runtime:funcs:fmt): sig -> res --- internal/runtime/funcs/print.go | 4 ++-- internal/runtime/funcs/println.go | 13 ++----------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/internal/runtime/funcs/print.go b/internal/runtime/funcs/print.go index 5167cbc3..1236324d 100644 --- a/internal/runtime/funcs/print.go +++ b/internal/runtime/funcs/print.go @@ -15,7 +15,7 @@ func (p print) Create(io runtime.IO, _ runtime.Msg) (func(ctx context.Context), return nil, err } - sigOut, err := io.Out.Single("sig") + resOut, err := io.Out.Single("res") if err != nil { return nil, err } @@ -27,7 +27,7 @@ func (p print) Create(io runtime.IO, _ runtime.Msg) (func(ctx context.Context), return } fmt.Print(data) - if !sigOut.Send(ctx, data) { + if !resOut.Send(ctx, data) { return } } diff --git a/internal/runtime/funcs/println.go b/internal/runtime/funcs/println.go index 771e013a..0b284721 100644 --- a/internal/runtime/funcs/println.go +++ b/internal/runtime/funcs/println.go @@ -15,17 +15,11 @@ func (p println) Create(io runtime.IO, _ runtime.Msg) (func(ctx context.Context) return nil, err } - sigOut, err := io.Out.Single("sig") + resOut, err := io.Out.Single("res") if err != nil { return nil, err } - // TODO - // errOut, err := io.Out.Single("err") - // if err != nil { - // return nil, err - // } - return func(ctx context.Context) { for { dataMsg, ok := dataIn.Receive(ctx) @@ -34,13 +28,10 @@ func (p println) Create(io runtime.IO, _ runtime.Msg) (func(ctx context.Context) } if _, err := fmt.Println(dataMsg); err != nil { - // if !errOut.Send(ctx, errFromErr(err)) { - // return - // } panic(err) } - if !sigOut.Send(ctx, dataMsg) { + if !resOut.Send(ctx, dataMsg) { return } } From c927c16c6eec4b7dc425b8bd38de3f3d7668d6f5 Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Sat, 7 Dec 2024 04:48:33 +0500 Subject: [PATCH 07/28] refactor(compiler): meta and error --- internal/compiler/compiler.go | 20 ++++++++++++++------ internal/compiler/contract.go | 11 ++++++----- internal/compiler/error.go | 15 ++++----------- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/internal/compiler/compiler.go b/internal/compiler/compiler.go index 9a20883e..9c5f4872 100644 --- a/internal/compiler/compiler.go +++ b/internal/compiler/compiler.go @@ -6,6 +6,7 @@ import ( "github.com/nevalang/neva/internal/compiler/ir" "github.com/nevalang/neva/internal/compiler/sourcecode" + "github.com/nevalang/neva/internal/compiler/sourcecode/core" ) type Compiler struct { @@ -48,7 +49,7 @@ type FrontendResult struct { func (f Frontend) Process(ctx context.Context, main string) (FrontendResult, *Error) { raw, root, err := f.builder.Build(ctx, main) if err != nil { - return FrontendResult{}, Error{Location: &sourcecode.Location{Package: main}}.Wrap(err) + return FrontendResult{}, err } parsedMods, err := f.parser.ParseModules(raw.Modules) @@ -81,7 +82,7 @@ func NewFrontend(builder Builder, parser Parser) Frontend { type Middleend struct { desugarer Desugarer analyzer Analyzer - irgen IRGenerator + irgen Irgen } type MiddleendResult struct { @@ -104,9 +105,16 @@ func (m Middleend) Process(feResult FrontendResult) (MiddleendResult, *Error) { return MiddleendResult{}, err } - irProg, err := m.irgen.Generate(desugaredBuild, feResult.MainPkg) - if err != nil { - return MiddleendResult{}, err + irProg, irerr := m.irgen.Generate(desugaredBuild, feResult.MainPkg) + if irerr != nil { + return MiddleendResult{}, &Error{ + Message: "internal error: unable to generate IR", + Meta: &core.Meta{ + Location: core.Location{ + ModRef: desugaredBuild.EntryModRef, + }, + }, + } } return MiddleendResult{ @@ -121,7 +129,7 @@ func New( parser Parser, desugarer Desugarer, analyzer Analyzer, - irgen IRGenerator, + irgen Irgen, backend Backend, ) Compiler { return Compiler{ diff --git a/internal/compiler/contract.go b/internal/compiler/contract.go index 36753183..d98677a0 100644 --- a/internal/compiler/contract.go +++ b/internal/compiler/contract.go @@ -5,6 +5,7 @@ import ( "github.com/nevalang/neva/internal/compiler/ir" src "github.com/nevalang/neva/internal/compiler/sourcecode" + "github.com/nevalang/neva/internal/compiler/sourcecode/core" ) const ( @@ -19,12 +20,12 @@ type ( } RawBuild struct { - EntryModRef src.ModuleRef - Modules map[src.ModuleRef]RawModule + EntryModRef core.ModuleRef + Modules map[core.ModuleRef]RawModule } Parser interface { - ParseModules(rawMods map[src.ModuleRef]RawModule) (map[src.ModuleRef]src.Module, *Error) + ParseModules(rawMods map[core.ModuleRef]RawModule) (map[core.ModuleRef]src.Module, *Error) } RawModule struct { @@ -42,8 +43,8 @@ type ( Desugar(build src.Build) (src.Build, error) } - IRGenerator interface { - Generate(build src.Build, mainpkg string) (*ir.Program, *Error) + Irgen interface { + Generate(build src.Build, mainpkg string) (*ir.Program, error) } Backend interface { diff --git a/internal/compiler/error.go b/internal/compiler/error.go index 751263f4..48131833 100644 --- a/internal/compiler/error.go +++ b/internal/compiler/error.go @@ -3,14 +3,12 @@ package compiler import ( "fmt" - src "github.com/nevalang/neva/internal/compiler/sourcecode" "github.com/nevalang/neva/internal/compiler/sourcecode/core" ) type Error struct { - Message string - Location *src.Location - Meta *core.Meta + Message string + Meta *core.Meta child *Error } @@ -31,15 +29,10 @@ func (e *Error) Error() string { var s string current := e.unwrap() - hasLocation := current.Location != nil hasMeta := current.Meta != nil - if hasLocation && hasMeta { - s = fmt.Sprintf("%v:%v: %v", *current.Location, current.Meta.Start, current.Message) - } else if hasLocation { - s = fmt.Sprintf("%v: %v", *current.Location, current.Message) - } else if hasMeta { - s = fmt.Sprintf("%v: %v", current.Meta.Start, current.Message) + if hasMeta { + s = fmt.Sprintf("%v:%v: %v", current.Meta.Location, current.Meta.Start, current.Message) } else { s = current.Message } From 82967452e97b890a8b4ae9dc6ba4fd18a3ecccf4 Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Sat, 7 Dec 2024 04:50:17 +0500 Subject: [PATCH 08/28] refactor(compiler): meta, location and mod-ref, to core, update scope and typesystem; --- internal/compiler/sourcecode/core/core.go | 43 +++++++++-- internal/compiler/sourcecode/scope.go | 72 +++++++------------ internal/compiler/sourcecode/sourcecode.go | 27 +++---- .../sourcecode/typesystem/typesystem.go | 7 +- 4 files changed, 74 insertions(+), 75 deletions(-) diff --git a/internal/compiler/sourcecode/core/core.go b/internal/compiler/sourcecode/core/core.go index 705a27a9..a18bb3eb 100644 --- a/internal/compiler/sourcecode/core/core.go +++ b/internal/compiler/sourcecode/core/core.go @@ -3,7 +3,10 @@ package core -import "fmt" +import ( + "fmt" + "path/filepath" +) // EntityRef is a reference to an entity in the source code type EntityRef struct { @@ -21,9 +24,41 @@ func (e EntityRef) String() string { // Meta contains meta information about the source code type Meta struct { - Text string `json:"text,omitempty"` - Start Position `json:"start,omitempty"` - Stop Position `json:"stop,omitempty"` + Text string `json:"text,omitempty"` + Start Position `json:"start,omitempty"` + Stop Position `json:"stop,omitempty"` + Location Location `json:"location,omitempty"` +} + +type Location struct { + ModRef ModuleRef `json:"module,omitempty"` + Package string `json:"package,omitempty"` + Filename string `json:"filename,omitempty"` +} + +func (l Location) String() string { + var s string + if l.ModRef.Path == "@" { + s = l.Package + } else { + s = filepath.Join(l.ModRef.String(), l.Package) + } + if l.Filename != "" { + s = filepath.Join(s, l.Filename+".neva") + } + return s +} + +type ModuleRef struct { + Path string `json:"path,omitempty"` + Version string `json:"version,omitempty"` +} + +func (m ModuleRef) String() string { + if m.Version == "" { + return m.Path + } + return fmt.Sprintf("%v@%v", m.Path, m.Version) } // Position contains line and column numbers diff --git a/internal/compiler/sourcecode/scope.go b/internal/compiler/sourcecode/scope.go index d592580a..9a73f503 100644 --- a/internal/compiler/sourcecode/scope.go +++ b/internal/compiler/sourcecode/scope.go @@ -3,7 +3,6 @@ package sourcecode import ( "errors" "fmt" - "path/filepath" "github.com/nevalang/neva/internal/compiler/sourcecode/core" ts "github.com/nevalang/neva/internal/compiler/sourcecode/typesystem" @@ -11,7 +10,7 @@ import ( ) // NewScope returns a new scope with a given location -func NewScope(build Build, location Location) Scope { +func NewScope(build Build, location core.Location) Scope { return Scope{ loc: location, build: build, @@ -20,44 +19,23 @@ func NewScope(build Build, location Location) Scope { // Scope is an object that provides access to program entities type Scope struct { - loc Location + loc core.Location build Build } // Location returns a location of the current scope -func (s Scope) Location() *Location { +func (s Scope) Location() *core.Location { return &s.loc } // Relocate returns a new scope with a given location -func (s Scope) Relocate(location Location) Scope { +func (s Scope) Relocate(location core.Location) Scope { return Scope{ loc: location, build: s.build, } } -// Location is a source code location -type Location struct { - Module ModuleRef - Package string - Filename string -} - -// String returns location as a string -func (l Location) String() string { - var s string - if l.Module.Path == "@" { - s = l.Package - } else { - s = filepath.Join(l.Module.String(), l.Package) - } - if l.Filename != "" { - s = filepath.Join(s, l.Filename+".neva") - } - return s -} - // IsTopType returns true if expr is a top type (any) func (s Scope) IsTopType(expr ts.Expr) bool { if expr.Inst == nil { @@ -80,36 +58,36 @@ func (s Scope) GetType(ref core.EntityRef) (ts.Def, ts.Scope, error) { } // Entity returns entity by reference -func (s Scope) Entity(entityRef core.EntityRef) (Entity, Location, error) { +func (s Scope) Entity(entityRef core.EntityRef) (Entity, core.Location, error) { return s.entity(entityRef) } // entity is an alrogithm that resolves entity reference based on scope's location -func (s Scope) entity(entityRef core.EntityRef) (Entity, Location, error) { - curMod, ok := s.build.Modules[s.loc.Module] +func (s Scope) entity(entityRef core.EntityRef) (Entity, core.Location, error) { + curMod, ok := s.build.Modules[s.loc.ModRef] if !ok { - return Entity{}, Location{}, fmt.Errorf("module not found: %v", s.loc.Module) + return Entity{}, core.Location{}, fmt.Errorf("module not found: %v", s.loc.ModRef) } curPkg := curMod.Packages[s.loc.Package] if !ok { - return Entity{}, Location{}, fmt.Errorf("package not found: %v", s.loc.Package) + return Entity{}, core.Location{}, fmt.Errorf("package not found: %v", s.loc.Package) } if entityRef.Pkg == "" { // local reference (current package or builtin) entity, fileName, ok := curPkg.Entity(entityRef.Name) if ok { - return entity, Location{ - Module: s.loc.Module, + return entity, core.Location{ + ModRef: s.loc.ModRef, Package: s.loc.Package, Filename: fileName, }, nil } - stdModRef := ModuleRef{Path: "std", Version: pkg.Version} + stdModRef := core.ModuleRef{Path: "std", Version: pkg.Version} stdMod, ok := s.build.Modules[stdModRef] if !ok { - return Entity{}, Location{}, fmt.Errorf("std module not found: %v", stdModRef) + return Entity{}, core.Location{}, fmt.Errorf("std module not found: %v", stdModRef) } entity, fileName, err := stdMod.Entity(core.EntityRef{ @@ -117,11 +95,11 @@ func (s Scope) entity(entityRef core.EntityRef) (Entity, Location, error) { Name: entityRef.Name, }) if err != nil { - return Entity{}, Location{}, err + return Entity{}, core.Location{}, err } - return entity, Location{ - Module: stdModRef, + return entity, core.Location{ + ModRef: stdModRef, Package: "builtin", Filename: fileName, }, nil @@ -129,26 +107,26 @@ func (s Scope) entity(entityRef core.EntityRef) (Entity, Location, error) { curFile, ok := curPkg[s.loc.Filename] if !ok { - return Entity{}, Location{}, fmt.Errorf("file not found: %v", s.loc.Filename) + return Entity{}, core.Location{}, fmt.Errorf("file not found: %v", s.loc.Filename) } pkgImport, ok := curFile.Imports[entityRef.Pkg] if !ok { - return Entity{}, Location{}, fmt.Errorf("import not found: %v", entityRef.Pkg) + return Entity{}, core.Location{}, fmt.Errorf("import not found: %v", entityRef.Pkg) } var ( mod Module - modRef ModuleRef + modRef core.ModuleRef ) if pkgImport.Module == "@" { - modRef = s.loc.Module // FIXME s.Location.ModRef is where we are now (e.g. std) + modRef = s.loc.ModRef // FIXME s.Location.ModRef is where we are now (e.g. std) mod = curMod } else { modRef = curMod.Manifest.Deps[pkgImport.Module] depMod, ok := s.build.Modules[modRef] if !ok { - return Entity{}, Location{}, fmt.Errorf("dependency module not found: %v", modRef) + return Entity{}, core.Location{}, fmt.Errorf("dependency module not found: %v", modRef) } mod = depMod } @@ -160,15 +138,15 @@ func (s Scope) entity(entityRef core.EntityRef) (Entity, Location, error) { entity, fileName, err := mod.Entity(ref) if err != nil { - return Entity{}, Location{}, err + return Entity{}, core.Location{}, err } if !entity.IsPublic { - return Entity{}, Location{}, errors.New("entity is not public") + return Entity{}, core.Location{}, errors.New("entity is not public") } - return entity, Location{ - Module: modRef, + return entity, core.Location{ + ModRef: modRef, Package: pkgImport.Package, Filename: fileName, }, nil diff --git a/internal/compiler/sourcecode/sourcecode.go b/internal/compiler/sourcecode/sourcecode.go index 0f5b56aa..e5b16bfd 100644 --- a/internal/compiler/sourcecode/sourcecode.go +++ b/internal/compiler/sourcecode/sourcecode.go @@ -12,8 +12,8 @@ import ( // Build represents all the information in source code, that must be compiled. // User usually don't interacts with this abstraction, but it's important for compiler. type Build struct { - EntryModRef ModuleRef `json:"entryModRef,omitempty"` - Modules map[ModuleRef]Module `json:"modules,omitempty"` + EntryModRef core.ModuleRef `json:"entryModRef,omitempty"` + Modules map[core.ModuleRef]Module `json:"modules,omitempty"` } // Module is unit of distribution. @@ -37,20 +37,8 @@ func (mod Module) Entity(entityRef core.EntityRef) (entity Entity, filename stri } type ModuleManifest struct { - LanguageVersion string `json:"neva,omitempty" yaml:"neva,omitempty"` - Deps map[string]ModuleRef `json:"deps,omitempty" yaml:"deps,omitempty"` -} - -type ModuleRef struct { - Path string `json:"path,omitempty"` - Version string `json:"version,omitempty"` -} - -func (m ModuleRef) String() string { - if m.Version == "" { - return m.Path - } - return fmt.Sprintf("%v@%v", m.Path, m.Version) + LanguageVersion string `json:"neva,omitempty" yaml:"neva,omitempty"` + Deps map[string]core.ModuleRef `json:"deps,omitempty" yaml:"deps,omitempty"` } type Package map[string]File @@ -115,7 +103,7 @@ func (e Entity) Meta() *core.Meta { case ConstEntity: m = e.Const.Meta case TypeEntity: - m = e.Type.Meta.(core.Meta) //nolint + m = e.Type.Meta case InterfaceEntity: m = e.Interface.Meta case ComponentEntity: @@ -270,8 +258,9 @@ func (m MsgLiteral) String() string { } type IO struct { - In map[string]Port `json:"in,omitempty"` - Out map[string]Port `json:"out,omitempty"` + In map[string]Port `json:"in,omitempty"` + Out map[string]Port `json:"out,omitempty"` + Meta core.Meta `json:"meta,omitempty"` } type Port struct { diff --git a/internal/compiler/sourcecode/typesystem/typesystem.go b/internal/compiler/sourcecode/typesystem/typesystem.go index ba01812f..5b0a0a30 100644 --- a/internal/compiler/sourcecode/typesystem/typesystem.go +++ b/internal/compiler/sourcecode/typesystem/typesystem.go @@ -13,7 +13,7 @@ type Def struct { // Empty body means base type BodyExpr *Expr `json:"bodyExpr,omitempty"` // Meta can be used to store anything that can be useful for typesystem user. It is ignored by the typesystem itself. - Meta ExprMeta `json:"meta,omitempty"` + Meta core.Meta `json:"meta,omitempty"` } func (def Def) String() string { @@ -41,12 +41,9 @@ type Param struct { type Expr struct { Lit *LitExpr `json:"lit,omitempty"` Inst *InstExpr `json:"inst,omitempty"` - Meta ExprMeta `json:"meta,omitempty"` // This field must be ignored by the typesystem and only used outside + Meta core.Meta `json:"meta,omitempty"` // This field must be ignored by the typesystem and only used outside } -// ExprMeta can contain any meta information that typesystem user might need e.g. source code text representation. -type ExprMeta any - // String formats expression in a TS manner func (expr Expr) String() string { if expr.Inst == nil && expr.Lit == nil { From 47555a0519a71d0f222df9f65542fbb13560e5d7 Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Sat, 7 Dec 2024 04:51:01 +0500 Subject: [PATCH 09/28] refactor(irgen): get rid of compiler error --- internal/compiler/irgen/func.go | 7 ++--- internal/compiler/irgen/irgen.go | 42 ++++++++---------------------- internal/compiler/irgen/message.go | 16 +++++------- 3 files changed, 19 insertions(+), 46 deletions(-) diff --git a/internal/compiler/irgen/func.go b/internal/compiler/irgen/func.go index 6f864dac..3d2e88db 100644 --- a/internal/compiler/irgen/func.go +++ b/internal/compiler/irgen/func.go @@ -37,7 +37,7 @@ func (Generator) getFuncRef(component src.Component, nodeTypeArgs []ts.Expr) (st return "", errors.New("type argument mismatches runtime func directive") } -func getConfigMsg(node src.Node, scope src.Scope) (*ir.Message, *compiler.Error) { +func getConfigMsg(node src.Node, scope src.Scope) (*ir.Message, error) { args, ok := node.Directives[compiler.BindDirective] if !ok { return nil, nil @@ -45,10 +45,7 @@ func getConfigMsg(node src.Node, scope src.Scope) (*ir.Message, *compiler.Error) entity, location, err := scope.Entity(compiler.ParseEntityRef(args[0])) if err != nil { - return nil, &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), - } + return nil, err } return getIRMsgBySrcRef( diff --git a/internal/compiler/irgen/irgen.go b/internal/compiler/irgen/irgen.go index 2b424fcf..c63ca1f3 100644 --- a/internal/compiler/irgen/irgen.go +++ b/internal/compiler/irgen/irgen.go @@ -3,7 +3,6 @@ package irgen import ( "fmt" - "github.com/nevalang/neva/internal/compiler" "github.com/nevalang/neva/internal/compiler/ir" src "github.com/nevalang/neva/internal/compiler/sourcecode" "github.com/nevalang/neva/internal/compiler/sourcecode/core" @@ -32,9 +31,9 @@ type ( func (g Generator) Generate( build src.Build, mainPkgName string, -) (*ir.Program, *compiler.Error) { - scope := src.NewScope(build, src.Location{ - Module: build.EntryModRef, +) (*ir.Program, error) { + scope := src.NewScope(build, core.Location{ + ModRef: build.EntryModRef, Package: mainPkgName, Filename: "", }) @@ -63,9 +62,7 @@ func (g Generator) Generate( } if err := g.processNode(rootNodeCtx, scope, result); err != nil { - return nil, compiler.Error{ - Location: scope.Location(), - }.Wrap(err) + return nil, fmt.Errorf("process node: %w", err) } // graph reduction is not an optimization: @@ -82,13 +79,10 @@ func (g Generator) processNode( nodeCtx nodeContext, scope src.Scope, result *ir.Program, -) *compiler.Error { +) error { entity, location, err := scope.Entity(nodeCtx.node.EntityRef) if err != nil { - return &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), - } + return fmt.Errorf("get entity: %w", err) } component := entity.Component @@ -98,20 +92,13 @@ func (g Generator) processNode( runtimeFuncRef, err := g.getFuncRef(component, nodeCtx.node.TypeArgs) if err != nil { - return &compiler.Error{ - Message: err.Error(), - Location: &location, - Meta: &component.Meta, - } + return fmt.Errorf("get func ref: %w", err) } if runtimeFuncRef != "" { cfgMsg, err := getConfigMsg(nodeCtx.node, scope) if err != nil { - return &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), - } + return fmt.Errorf("get config msg: %w", err) } result.Funcs = append(result.Funcs, ir.FuncCall{ Ref: runtimeFuncRef, @@ -135,20 +122,13 @@ func (g Generator) processNode( result, ) if err != nil { - return &compiler.Error{ - Message: err.Error(), - Location: newScope.Location(), - } + return fmt.Errorf("process network: %w", err) } for nodeName, node := range component.Nodes { nodePortsUsage, ok := subnodesPortsUsage[nodeName] if !ok { - return &compiler.Error{ - Message: fmt.Sprintf("node usage not found: %v", nodeName), - Location: &location, - Meta: &node.Meta, - } + return fmt.Errorf("node usage not found: %v", nodeName) } // TODO e2e test @@ -183,7 +163,7 @@ func (g Generator) processNode( } if err := g.processNode(subNodeCtx, scopeToUse, result); err != nil { - return err + return fmt.Errorf("process node: %w", err) } } diff --git a/internal/compiler/irgen/message.go b/internal/compiler/irgen/message.go index 0332b1f3..8523fded 100644 --- a/internal/compiler/irgen/message.go +++ b/internal/compiler/irgen/message.go @@ -1,7 +1,9 @@ package irgen import ( - "github.com/nevalang/neva/internal/compiler" + "errors" + "fmt" + "github.com/nevalang/neva/internal/compiler/ir" src "github.com/nevalang/neva/internal/compiler/sourcecode" ts "github.com/nevalang/neva/internal/compiler/sourcecode/typesystem" @@ -11,14 +13,11 @@ func getIRMsgBySrcRef( constant src.ConstValue, scope src.Scope, typeExpr ts.Expr, -) (*ir.Message, *compiler.Error) { +) (*ir.Message, error) { if constant.Ref != nil { entity, location, err := scope.Entity(*constant.Ref) if err != nil { - return nil, &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), - } + return nil, fmt.Errorf("get entity: %w", err) } return getIRMsgBySrcRef(entity.Const.Value, scope.Relocate(location), typeExpr) } @@ -99,8 +98,5 @@ func getIRMsgBySrcRef( }, nil } - return nil, &compiler.Error{ - Message: "unknown msg type", - Location: scope.Location(), - } + return nil, errors.New("unknown msg type") } From f60f372768f6518c687b4e1ff4752cc2bcfddea7 Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Sat, 7 Dec 2024 04:51:48 +0500 Subject: [PATCH 10/28] fix(desugarer): upd after refactorign with core --- internal/compiler/desugarer/desugarer.go | 22 +++++++++---------- internal/compiler/desugarer/desugarer_test.go | 9 ++++---- internal/compiler/desugarer/mocks_test.go | 10 ++++----- internal/compiler/desugarer/network_test.go | 4 ++-- 4 files changed, 23 insertions(+), 22 deletions(-) diff --git a/internal/compiler/desugarer/desugarer.go b/internal/compiler/desugarer/desugarer.go index 90ed21fb..5633c7b9 100644 --- a/internal/compiler/desugarer/desugarer.go +++ b/internal/compiler/desugarer/desugarer.go @@ -47,7 +47,7 @@ type Desugarer struct { } func (d *Desugarer) Desugar(build src.Build) (src.Build, error) { - desugaredMods := make(map[src.ModuleRef]src.Module, len(build.Modules)) + desugaredMods := make(map[core.ModuleRef]src.Module, len(build.Modules)) for modRef := range build.Modules { desugaredMod, err := d.desugarModule(build, modRef) @@ -65,17 +65,17 @@ func (d *Desugarer) Desugar(build src.Build) (src.Build, error) { func (d *Desugarer) desugarModule( build src.Build, - modRef src.ModuleRef, + modRef core.ModuleRef, ) (src.Module, error) { mod := build.Modules[modRef] // create manifest copy with std module dependency desugaredManifest := src.ModuleManifest{ LanguageVersion: mod.Manifest.LanguageVersion, - Deps: make(map[string]src.ModuleRef, len(mod.Manifest.Deps)+1), + Deps: make(map[string]core.ModuleRef, len(mod.Manifest.Deps)+1), } maps.Copy(desugaredManifest.Deps, mod.Manifest.Deps) - desugaredManifest.Deps["std"] = src.ModuleRef{Path: "std", Version: pkg.Version} + desugaredManifest.Deps["std"] = core.ModuleRef{Path: "std", Version: pkg.Version} // copy all modules but replace manifest in current one modsCopy := maps.Clone(build.Modules) @@ -94,8 +94,8 @@ func (d *Desugarer) desugarModule( for pkgName, pkg := range mod.Packages { // it's important to patch build before desugar package so we can resolve references to std - scope := src.NewScope(build, src.Location{ - Module: modRef, + scope := src.NewScope(build, core.Location{ + ModRef: modRef, Package: pkgName, }) @@ -117,17 +117,17 @@ func (d *Desugarer) desugarModule( // //go:generate mockgen -source $GOFILE -destination mocks_test.go -package ${GOPACKAGE} type Scope interface { - Entity(ref core.EntityRef) (src.Entity, src.Location, error) - Relocate(location src.Location) src.Scope - Location() *src.Location + Entity(ref core.EntityRef) (src.Entity, core.Location, error) + Relocate(location core.Location) src.Scope + Location() *core.Location } func (d *Desugarer) desugarPkg(pkg src.Package, scope Scope) (src.Package, error) { desugaredPkgs := make(src.Package, len(pkg)) for fileName, file := range pkg { - newScope := scope.Relocate(src.Location{ - Module: scope.Location().Module, + newScope := scope.Relocate(core.Location{ + ModRef: scope.Location().ModRef, Package: scope.Location().Package, Filename: fileName, }) diff --git a/internal/compiler/desugarer/desugarer_test.go b/internal/compiler/desugarer/desugarer_test.go index d7307233..39d8237f 100644 --- a/internal/compiler/desugarer/desugarer_test.go +++ b/internal/compiler/desugarer/desugarer_test.go @@ -4,6 +4,7 @@ import ( "testing" src "github.com/nevalang/neva/internal/compiler/sourcecode" + "github.com/nevalang/neva/internal/compiler/sourcecode/core" "github.com/nevalang/neva/pkg" "github.com/stretchr/testify/require" ) @@ -20,7 +21,7 @@ func TestDesugarer_desugarModule(t *testing.T) { name: "every desugared module has std mod dep with right version", mod: src.Module{ Manifest: src.ModuleManifest{ - Deps: map[string]src.ModuleRef{}, // <-- no std mod dep + Deps: map[string]core.ModuleRef{}, // <-- no std mod dep }, Packages: map[string]src.Package{}, }, @@ -39,9 +40,9 @@ func TestDesugarer_desugarModule(t *testing.T) { for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { - modRef := src.ModuleRef{Path: "@"} + modRef := core.ModuleRef{Path: "@"} build := src.Build{ - Modules: map[src.ModuleRef]src.Module{ + Modules: map[core.ModuleRef]src.Module{ modRef: tt.mod, }, } @@ -96,7 +97,7 @@ func defaultImports() map[string]src.Import { } } -var defaultDeps = map[string]src.ModuleRef{ +var defaultDeps = map[string]core.ModuleRef{ "std": { Path: "std", Version: pkg.Version, diff --git a/internal/compiler/desugarer/mocks_test.go b/internal/compiler/desugarer/mocks_test.go index 01b7c189..50a939b7 100644 --- a/internal/compiler/desugarer/mocks_test.go +++ b/internal/compiler/desugarer/mocks_test.go @@ -36,11 +36,11 @@ func (m *MockScope) EXPECT() *MockScopeMockRecorder { } // Entity mocks base method. -func (m *MockScope) Entity(ref core.EntityRef) (sourcecode.Entity, sourcecode.Location, error) { +func (m *MockScope) Entity(ref core.EntityRef) (sourcecode.Entity, core.Location, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Entity", ref) ret0, _ := ret[0].(sourcecode.Entity) - ret1, _ := ret[1].(sourcecode.Location) + ret1, _ := ret[1].(core.Location) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } @@ -52,10 +52,10 @@ func (mr *MockScopeMockRecorder) Entity(ref interface{}) *gomock.Call { } // Location mocks base method. -func (m *MockScope) Location() *sourcecode.Location { +func (m *MockScope) Location() *core.Location { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Location") - ret0, _ := ret[0].(*sourcecode.Location) + ret0, _ := ret[0].(*core.Location) return ret0 } @@ -66,7 +66,7 @@ func (mr *MockScopeMockRecorder) Location() *gomock.Call { } // Relocate mocks base method. -func (m *MockScope) Relocate(location sourcecode.Location) sourcecode.Scope { +func (m *MockScope) Relocate(location core.Location) sourcecode.Scope { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Relocate", location) ret0, _ := ret[0].(sourcecode.Scope) diff --git a/internal/compiler/desugarer/network_test.go b/internal/compiler/desugarer/network_test.go index 9fc3deb8..16b872f8 100644 --- a/internal/compiler/desugarer/network_test.go +++ b/internal/compiler/desugarer/network_test.go @@ -560,7 +560,7 @@ func TestDesugarNetwork(t *testing.T) { } mock. Entity(core.EntityRef{Name: "foo"}). - Return(src.Entity{Kind: src.ConstEntity, Const: constEntity}, src.Location{}, nil) + Return(src.Entity{Kind: src.ConstEntity, Const: constEntity}, core.Location{}, nil) }, expectedResult: handleNetworkResult{ desugaredConnections: []src.Connection{ @@ -648,7 +648,7 @@ func TestDesugarNetwork(t *testing.T) { } mock. Entity(core.EntityRef{Name: "c"}). - Return(src.Entity{Kind: src.ConstEntity, Const: constEntity}, src.Location{}, nil) + Return(src.Entity{Kind: src.ConstEntity, Const: constEntity}, core.Location{}, nil) }, expectedResult: handleNetworkResult{ desugaredConnections: []src.Connection{ From 2c4b42c962fbb678dd514ed06fdea109843a05ed Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Sat, 7 Dec 2024 04:52:40 +0500 Subject: [PATCH 11/28] feat(parser): fill meta for each entity at each parsing step --- .../compiler/parser/generated/neva.interp | 2 +- .../compiler/parser/generated/neva_parser.go | 70 +- internal/compiler/parser/listener.go | 67 +- internal/compiler/parser/listener_helpers.go | 888 ++++++++++++++++-- internal/compiler/parser/manifest.go | 5 +- internal/compiler/parser/network.go | 665 ------------- internal/compiler/parser/neva.g4 | 2 +- internal/compiler/parser/parser.go | 43 +- internal/compiler/parser/parser_test.go | 46 +- 9 files changed, 931 insertions(+), 857 deletions(-) delete mode 100644 internal/compiler/parser/network.go diff --git a/internal/compiler/parser/generated/neva.interp b/internal/compiler/parser/generated/neva.interp index 8dae3ebb..07b3888e 100644 --- a/internal/compiler/parser/generated/neva.interp +++ b/internal/compiler/parser/generated/neva.interp @@ -218,4 +218,4 @@ defaultCase atn: -[4, 1, 58, 1116, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, 2, 92, 7, 92, 2, 93, 7, 93, 1, 0, 1, 0, 1, 0, 5, 0, 192, 8, 0, 10, 0, 12, 0, 195, 9, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 204, 8, 1, 1, 2, 1, 2, 1, 2, 4, 2, 209, 8, 2, 11, 2, 12, 2, 210, 1, 3, 1, 3, 1, 3, 3, 3, 216, 8, 3, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 222, 8, 4, 10, 4, 12, 4, 225, 9, 4, 1, 4, 1, 4, 1, 5, 4, 5, 230, 8, 5, 11, 5, 12, 5, 231, 1, 6, 1, 6, 5, 6, 236, 8, 6, 10, 6, 12, 6, 239, 9, 6, 1, 6, 1, 6, 5, 6, 243, 8, 6, 10, 6, 12, 6, 246, 9, 6, 1, 6, 5, 6, 249, 8, 6, 10, 6, 12, 6, 252, 9, 6, 1, 6, 1, 6, 1, 7, 3, 7, 257, 8, 7, 1, 7, 1, 7, 3, 7, 261, 8, 7, 1, 7, 5, 7, 264, 8, 7, 10, 7, 12, 7, 267, 9, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 3, 9, 274, 8, 9, 1, 9, 1, 9, 1, 10, 1, 10, 3, 10, 280, 8, 10, 1, 11, 1, 11, 1, 11, 1, 11, 5, 11, 286, 8, 11, 10, 11, 12, 11, 289, 9, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 5, 13, 296, 8, 13, 10, 13, 12, 13, 299, 9, 13, 1, 14, 1, 14, 3, 14, 303, 8, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 3, 19, 316, 8, 19, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 3, 20, 323, 8, 20, 1, 20, 3, 20, 326, 8, 20, 1, 20, 3, 20, 329, 8, 20, 1, 21, 1, 21, 5, 21, 333, 8, 21, 10, 21, 12, 21, 336, 9, 21, 1, 21, 3, 21, 339, 8, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 5, 22, 346, 8, 22, 10, 22, 12, 22, 349, 9, 22, 1, 22, 5, 22, 352, 8, 22, 10, 22, 12, 22, 355, 9, 22, 1, 23, 1, 23, 3, 23, 359, 8, 23, 1, 23, 5, 23, 362, 8, 23, 10, 23, 12, 23, 365, 9, 23, 1, 24, 1, 24, 1, 24, 3, 24, 370, 8, 24, 1, 25, 1, 25, 3, 25, 374, 8, 25, 1, 26, 1, 26, 5, 26, 378, 8, 26, 10, 26, 12, 26, 381, 9, 26, 1, 26, 1, 26, 1, 26, 5, 26, 386, 8, 26, 10, 26, 12, 26, 389, 9, 26, 1, 26, 5, 26, 392, 8, 26, 10, 26, 12, 26, 395, 9, 26, 1, 26, 5, 26, 398, 8, 26, 10, 26, 12, 26, 401, 9, 26, 1, 26, 1, 26, 1, 27, 1, 27, 3, 27, 407, 8, 27, 1, 28, 1, 28, 5, 28, 411, 8, 28, 10, 28, 12, 28, 414, 9, 28, 1, 28, 1, 28, 5, 28, 418, 8, 28, 10, 28, 12, 28, 421, 9, 28, 1, 28, 1, 28, 1, 28, 5, 28, 426, 8, 28, 10, 28, 12, 28, 429, 9, 28, 1, 28, 5, 28, 432, 8, 28, 10, 28, 12, 28, 435, 9, 28, 1, 28, 5, 28, 438, 8, 28, 10, 28, 12, 28, 441, 9, 28, 1, 28, 1, 28, 1, 29, 1, 29, 5, 29, 447, 8, 29, 10, 29, 12, 29, 450, 9, 29, 1, 29, 1, 29, 5, 29, 454, 8, 29, 10, 29, 12, 29, 457, 9, 29, 1, 29, 3, 29, 460, 8, 29, 1, 29, 1, 29, 1, 30, 1, 30, 4, 30, 466, 8, 30, 11, 30, 12, 30, 467, 1, 30, 5, 30, 471, 8, 30, 10, 30, 12, 30, 474, 9, 30, 1, 31, 1, 31, 1, 31, 5, 31, 479, 8, 31, 10, 31, 12, 31, 482, 9, 31, 1, 32, 1, 32, 5, 32, 486, 8, 32, 10, 32, 12, 32, 489, 9, 32, 1, 32, 1, 32, 5, 32, 493, 8, 32, 10, 32, 12, 32, 496, 9, 32, 1, 32, 4, 32, 499, 8, 32, 11, 32, 12, 32, 500, 1, 33, 1, 33, 3, 33, 505, 8, 33, 1, 34, 3, 34, 508, 8, 34, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 3, 35, 515, 8, 35, 1, 35, 1, 35, 1, 35, 5, 35, 520, 8, 35, 10, 35, 12, 35, 523, 9, 35, 1, 36, 1, 36, 1, 37, 1, 37, 1, 38, 1, 38, 5, 38, 531, 8, 38, 10, 38, 12, 38, 534, 9, 38, 1, 38, 3, 38, 537, 8, 38, 1, 38, 1, 38, 1, 38, 5, 38, 542, 8, 38, 10, 38, 12, 38, 545, 9, 38, 3, 38, 547, 8, 38, 1, 38, 1, 38, 1, 39, 1, 39, 3, 39, 553, 8, 39, 1, 40, 5, 40, 556, 8, 40, 10, 40, 12, 40, 559, 9, 40, 1, 40, 1, 40, 3, 40, 563, 8, 40, 1, 40, 5, 40, 566, 8, 40, 10, 40, 12, 40, 569, 9, 40, 1, 41, 5, 41, 572, 8, 41, 10, 41, 12, 41, 575, 9, 41, 1, 41, 1, 41, 1, 41, 1, 41, 3, 41, 581, 8, 41, 1, 41, 5, 41, 584, 8, 41, 10, 41, 12, 41, 587, 9, 41, 1, 42, 3, 42, 590, 8, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 3, 43, 600, 8, 43, 1, 43, 5, 43, 603, 8, 43, 10, 43, 12, 43, 606, 9, 43, 1, 44, 1, 44, 3, 44, 610, 8, 44, 1, 44, 1, 44, 3, 44, 614, 8, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 3, 44, 621, 8, 44, 1, 45, 1, 45, 3, 45, 625, 8, 45, 1, 45, 1, 45, 3, 45, 629, 8, 45, 1, 45, 1, 45, 1, 45, 3, 45, 634, 8, 45, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 5, 48, 644, 8, 48, 10, 48, 12, 48, 647, 9, 48, 1, 48, 3, 48, 650, 8, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 5, 49, 658, 8, 49, 10, 49, 12, 49, 661, 9, 49, 1, 49, 1, 49, 5, 49, 665, 8, 49, 10, 49, 12, 49, 668, 9, 49, 5, 49, 670, 8, 49, 10, 49, 12, 49, 673, 9, 49, 3, 49, 675, 8, 49, 1, 50, 1, 50, 3, 50, 679, 8, 50, 1, 51, 1, 51, 5, 51, 683, 8, 51, 10, 51, 12, 51, 686, 9, 51, 1, 51, 3, 51, 689, 8, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 5, 52, 696, 8, 52, 10, 52, 12, 52, 699, 9, 52, 1, 52, 5, 52, 702, 8, 52, 10, 52, 12, 52, 705, 9, 52, 1, 53, 1, 53, 1, 53, 1, 53, 5, 53, 711, 8, 53, 10, 53, 12, 53, 714, 9, 53, 1, 54, 3, 54, 717, 8, 54, 1, 54, 3, 54, 720, 8, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 3, 55, 727, 8, 55, 1, 55, 5, 55, 730, 8, 55, 10, 55, 12, 55, 733, 9, 55, 1, 56, 1, 56, 5, 56, 737, 8, 56, 10, 56, 12, 56, 740, 9, 56, 1, 56, 1, 56, 5, 56, 744, 8, 56, 10, 56, 12, 56, 747, 9, 56, 5, 56, 749, 8, 56, 10, 56, 12, 56, 752, 9, 56, 1, 56, 1, 56, 5, 56, 756, 8, 56, 10, 56, 12, 56, 759, 9, 56, 3, 56, 761, 8, 56, 1, 56, 1, 56, 5, 56, 765, 8, 56, 10, 56, 12, 56, 768, 9, 56, 5, 56, 770, 8, 56, 10, 56, 12, 56, 773, 9, 56, 1, 56, 1, 56, 5, 56, 777, 8, 56, 10, 56, 12, 56, 780, 9, 56, 3, 56, 782, 8, 56, 1, 56, 1, 56, 5, 56, 786, 8, 56, 10, 56, 12, 56, 789, 9, 56, 5, 56, 791, 8, 56, 10, 56, 12, 56, 794, 9, 56, 1, 56, 1, 56, 1, 57, 1, 57, 4, 57, 800, 8, 57, 11, 57, 12, 57, 801, 1, 57, 1, 57, 1, 58, 1, 58, 3, 58, 808, 8, 58, 1, 58, 3, 58, 811, 8, 58, 1, 58, 5, 58, 814, 8, 58, 10, 58, 12, 58, 817, 9, 58, 4, 58, 819, 8, 58, 11, 58, 12, 58, 820, 1, 59, 3, 59, 824, 8, 59, 1, 59, 3, 59, 827, 8, 59, 1, 59, 1, 59, 1, 60, 1, 60, 5, 60, 833, 8, 60, 10, 60, 12, 60, 836, 9, 60, 1, 60, 3, 60, 839, 8, 60, 1, 60, 5, 60, 842, 8, 60, 10, 60, 12, 60, 845, 9, 60, 1, 60, 3, 60, 848, 8, 60, 1, 60, 3, 60, 851, 8, 60, 1, 61, 1, 61, 1, 62, 1, 62, 5, 62, 857, 8, 62, 10, 62, 12, 62, 860, 9, 62, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 3, 63, 867, 8, 63, 1, 63, 5, 63, 870, 8, 63, 10, 63, 12, 63, 873, 9, 63, 1, 63, 1, 63, 3, 63, 877, 8, 63, 5, 63, 879, 8, 63, 10, 63, 12, 63, 882, 9, 63, 1, 64, 1, 64, 3, 64, 886, 8, 64, 1, 65, 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 3, 66, 894, 8, 66, 1, 67, 1, 67, 5, 67, 898, 8, 67, 10, 67, 12, 67, 901, 9, 67, 1, 67, 1, 67, 1, 67, 5, 67, 906, 8, 67, 10, 67, 12, 67, 909, 9, 67, 1, 67, 1, 67, 5, 67, 913, 8, 67, 10, 67, 12, 67, 916, 9, 67, 5, 67, 918, 8, 67, 10, 67, 12, 67, 921, 9, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 3, 69, 937, 8, 69, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 74, 1, 74, 1, 75, 1, 75, 3, 75, 962, 8, 75, 1, 76, 1, 76, 1, 77, 1, 77, 5, 77, 968, 8, 77, 10, 77, 12, 77, 971, 9, 77, 1, 77, 1, 77, 5, 77, 975, 8, 77, 10, 77, 12, 77, 978, 9, 77, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 1, 79, 1, 79, 1, 79, 1, 79, 1, 80, 3, 80, 990, 8, 80, 1, 80, 1, 80, 1, 81, 1, 81, 1, 81, 1, 81, 3, 81, 998, 8, 81, 1, 82, 1, 82, 1, 83, 1, 83, 1, 83, 1, 84, 3, 84, 1006, 8, 84, 1, 84, 1, 84, 1, 84, 1, 85, 3, 85, 1012, 8, 85, 1, 85, 1, 85, 1, 85, 1, 85, 1, 86, 1, 86, 1, 87, 1, 87, 1, 88, 1, 88, 1, 88, 1, 88, 1, 89, 1, 89, 1, 89, 1, 89, 5, 89, 1030, 8, 89, 10, 89, 12, 89, 1033, 9, 89, 1, 90, 1, 90, 1, 90, 1, 90, 3, 90, 1039, 8, 90, 1, 91, 1, 91, 5, 91, 1043, 8, 91, 10, 91, 12, 91, 1046, 9, 91, 1, 91, 1, 91, 1, 91, 5, 91, 1051, 8, 91, 10, 91, 12, 91, 1054, 9, 91, 1, 91, 1, 91, 5, 91, 1058, 8, 91, 10, 91, 12, 91, 1061, 9, 91, 5, 91, 1063, 8, 91, 10, 91, 12, 91, 1066, 9, 91, 1, 91, 1, 91, 1, 92, 1, 92, 5, 92, 1072, 8, 92, 10, 92, 12, 92, 1075, 9, 92, 1, 92, 1, 92, 5, 92, 1079, 8, 92, 10, 92, 12, 92, 1082, 9, 92, 1, 92, 1, 92, 4, 92, 1086, 8, 92, 11, 92, 12, 92, 1087, 1, 92, 5, 92, 1091, 8, 92, 10, 92, 12, 92, 1094, 9, 92, 1, 92, 4, 92, 1097, 8, 92, 11, 92, 12, 92, 1098, 1, 92, 3, 92, 1102, 8, 92, 1, 92, 5, 92, 1105, 8, 92, 10, 92, 12, 92, 1108, 9, 92, 1, 92, 1, 92, 1, 93, 1, 93, 1, 93, 1, 93, 1, 93, 0, 0, 94, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 0, 4, 1, 0, 10, 11, 1, 0, 23, 24, 2, 0, 31, 33, 54, 54, 5, 0, 10, 10, 13, 14, 17, 17, 34, 45, 54, 54, 1189, 0, 193, 1, 0, 0, 0, 2, 203, 1, 0, 0, 0, 4, 208, 1, 0, 0, 0, 6, 212, 1, 0, 0, 0, 8, 217, 1, 0, 0, 0, 10, 229, 1, 0, 0, 0, 12, 233, 1, 0, 0, 0, 14, 256, 1, 0, 0, 0, 16, 268, 1, 0, 0, 0, 18, 273, 1, 0, 0, 0, 20, 279, 1, 0, 0, 0, 22, 281, 1, 0, 0, 0, 24, 290, 1, 0, 0, 0, 26, 292, 1, 0, 0, 0, 28, 302, 1, 0, 0, 0, 30, 304, 1, 0, 0, 0, 32, 306, 1, 0, 0, 0, 34, 310, 1, 0, 0, 0, 36, 312, 1, 0, 0, 0, 38, 315, 1, 0, 0, 0, 40, 320, 1, 0, 0, 0, 42, 330, 1, 0, 0, 0, 44, 342, 1, 0, 0, 0, 46, 356, 1, 0, 0, 0, 48, 369, 1, 0, 0, 0, 50, 371, 1, 0, 0, 0, 52, 375, 1, 0, 0, 0, 54, 406, 1, 0, 0, 0, 56, 408, 1, 0, 0, 0, 58, 444, 1, 0, 0, 0, 60, 463, 1, 0, 0, 0, 62, 475, 1, 0, 0, 0, 64, 483, 1, 0, 0, 0, 66, 504, 1, 0, 0, 0, 68, 507, 1, 0, 0, 0, 70, 512, 1, 0, 0, 0, 72, 524, 1, 0, 0, 0, 74, 526, 1, 0, 0, 0, 76, 528, 1, 0, 0, 0, 78, 552, 1, 0, 0, 0, 80, 557, 1, 0, 0, 0, 82, 573, 1, 0, 0, 0, 84, 589, 1, 0, 0, 0, 86, 594, 1, 0, 0, 0, 88, 620, 1, 0, 0, 0, 90, 633, 1, 0, 0, 0, 92, 635, 1, 0, 0, 0, 94, 637, 1, 0, 0, 0, 96, 641, 1, 0, 0, 0, 98, 674, 1, 0, 0, 0, 100, 678, 1, 0, 0, 0, 102, 680, 1, 0, 0, 0, 104, 692, 1, 0, 0, 0, 106, 706, 1, 0, 0, 0, 108, 716, 1, 0, 0, 0, 110, 724, 1, 0, 0, 0, 112, 734, 1, 0, 0, 0, 114, 797, 1, 0, 0, 0, 116, 818, 1, 0, 0, 0, 118, 823, 1, 0, 0, 0, 120, 830, 1, 0, 0, 0, 122, 852, 1, 0, 0, 0, 124, 854, 1, 0, 0, 0, 126, 866, 1, 0, 0, 0, 128, 885, 1, 0, 0, 0, 130, 887, 1, 0, 0, 0, 132, 893, 1, 0, 0, 0, 134, 895, 1, 0, 0, 0, 136, 924, 1, 0, 0, 0, 138, 936, 1, 0, 0, 0, 140, 938, 1, 0, 0, 0, 142, 941, 1, 0, 0, 0, 144, 943, 1, 0, 0, 0, 146, 951, 1, 0, 0, 0, 148, 957, 1, 0, 0, 0, 150, 961, 1, 0, 0, 0, 152, 963, 1, 0, 0, 0, 154, 965, 1, 0, 0, 0, 156, 981, 1, 0, 0, 0, 158, 984, 1, 0, 0, 0, 160, 989, 1, 0, 0, 0, 162, 997, 1, 0, 0, 0, 164, 999, 1, 0, 0, 0, 166, 1001, 1, 0, 0, 0, 168, 1005, 1, 0, 0, 0, 170, 1011, 1, 0, 0, 0, 172, 1017, 1, 0, 0, 0, 174, 1019, 1, 0, 0, 0, 176, 1021, 1, 0, 0, 0, 178, 1025, 1, 0, 0, 0, 180, 1038, 1, 0, 0, 0, 182, 1040, 1, 0, 0, 0, 184, 1069, 1, 0, 0, 0, 186, 1111, 1, 0, 0, 0, 188, 192, 5, 57, 0, 0, 189, 192, 5, 50, 0, 0, 190, 192, 3, 2, 1, 0, 191, 188, 1, 0, 0, 0, 191, 189, 1, 0, 0, 0, 191, 190, 1, 0, 0, 0, 192, 195, 1, 0, 0, 0, 193, 191, 1, 0, 0, 0, 193, 194, 1, 0, 0, 0, 194, 196, 1, 0, 0, 0, 195, 193, 1, 0, 0, 0, 196, 197, 5, 0, 0, 1, 197, 1, 1, 0, 0, 0, 198, 204, 3, 12, 6, 0, 199, 204, 3, 38, 19, 0, 200, 204, 3, 68, 34, 0, 201, 204, 3, 84, 42, 0, 202, 204, 3, 108, 54, 0, 203, 198, 1, 0, 0, 0, 203, 199, 1, 0, 0, 0, 203, 200, 1, 0, 0, 0, 203, 201, 1, 0, 0, 0, 203, 202, 1, 0, 0, 0, 204, 3, 1, 0, 0, 0, 205, 206, 3, 6, 3, 0, 206, 207, 5, 57, 0, 0, 207, 209, 1, 0, 0, 0, 208, 205, 1, 0, 0, 0, 209, 210, 1, 0, 0, 0, 210, 208, 1, 0, 0, 0, 210, 211, 1, 0, 0, 0, 211, 5, 1, 0, 0, 0, 212, 213, 5, 1, 0, 0, 213, 215, 5, 52, 0, 0, 214, 216, 3, 8, 4, 0, 215, 214, 1, 0, 0, 0, 215, 216, 1, 0, 0, 0, 216, 7, 1, 0, 0, 0, 217, 218, 5, 2, 0, 0, 218, 223, 3, 10, 5, 0, 219, 220, 5, 3, 0, 0, 220, 222, 3, 10, 5, 0, 221, 219, 1, 0, 0, 0, 222, 225, 1, 0, 0, 0, 223, 221, 1, 0, 0, 0, 223, 224, 1, 0, 0, 0, 224, 226, 1, 0, 0, 0, 225, 223, 1, 0, 0, 0, 226, 227, 5, 4, 0, 0, 227, 9, 1, 0, 0, 0, 228, 230, 5, 52, 0, 0, 229, 228, 1, 0, 0, 0, 230, 231, 1, 0, 0, 0, 231, 229, 1, 0, 0, 0, 231, 232, 1, 0, 0, 0, 232, 11, 1, 0, 0, 0, 233, 237, 5, 5, 0, 0, 234, 236, 5, 57, 0, 0, 235, 234, 1, 0, 0, 0, 236, 239, 1, 0, 0, 0, 237, 235, 1, 0, 0, 0, 237, 238, 1, 0, 0, 0, 238, 240, 1, 0, 0, 0, 239, 237, 1, 0, 0, 0, 240, 244, 5, 6, 0, 0, 241, 243, 5, 57, 0, 0, 242, 241, 1, 0, 0, 0, 243, 246, 1, 0, 0, 0, 244, 242, 1, 0, 0, 0, 244, 245, 1, 0, 0, 0, 245, 250, 1, 0, 0, 0, 246, 244, 1, 0, 0, 0, 247, 249, 3, 14, 7, 0, 248, 247, 1, 0, 0, 0, 249, 252, 1, 0, 0, 0, 250, 248, 1, 0, 0, 0, 250, 251, 1, 0, 0, 0, 251, 253, 1, 0, 0, 0, 252, 250, 1, 0, 0, 0, 253, 254, 5, 7, 0, 0, 254, 13, 1, 0, 0, 0, 255, 257, 3, 16, 8, 0, 256, 255, 1, 0, 0, 0, 256, 257, 1, 0, 0, 0, 257, 258, 1, 0, 0, 0, 258, 260, 3, 18, 9, 0, 259, 261, 5, 3, 0, 0, 260, 259, 1, 0, 0, 0, 260, 261, 1, 0, 0, 0, 261, 265, 1, 0, 0, 0, 262, 264, 5, 57, 0, 0, 263, 262, 1, 0, 0, 0, 264, 267, 1, 0, 0, 0, 265, 263, 1, 0, 0, 0, 265, 266, 1, 0, 0, 0, 266, 15, 1, 0, 0, 0, 267, 265, 1, 0, 0, 0, 268, 269, 5, 52, 0, 0, 269, 17, 1, 0, 0, 0, 270, 271, 3, 20, 10, 0, 271, 272, 5, 8, 0, 0, 272, 274, 1, 0, 0, 0, 273, 270, 1, 0, 0, 0, 273, 274, 1, 0, 0, 0, 274, 275, 1, 0, 0, 0, 275, 276, 3, 26, 13, 0, 276, 19, 1, 0, 0, 0, 277, 280, 5, 9, 0, 0, 278, 280, 3, 22, 11, 0, 279, 277, 1, 0, 0, 0, 279, 278, 1, 0, 0, 0, 280, 21, 1, 0, 0, 0, 281, 287, 5, 52, 0, 0, 282, 283, 3, 24, 12, 0, 283, 284, 5, 52, 0, 0, 284, 286, 1, 0, 0, 0, 285, 282, 1, 0, 0, 0, 286, 289, 1, 0, 0, 0, 287, 285, 1, 0, 0, 0, 287, 288, 1, 0, 0, 0, 288, 23, 1, 0, 0, 0, 289, 287, 1, 0, 0, 0, 290, 291, 7, 0, 0, 0, 291, 25, 1, 0, 0, 0, 292, 297, 5, 52, 0, 0, 293, 294, 5, 10, 0, 0, 294, 296, 5, 52, 0, 0, 295, 293, 1, 0, 0, 0, 296, 299, 1, 0, 0, 0, 297, 295, 1, 0, 0, 0, 297, 298, 1, 0, 0, 0, 298, 27, 1, 0, 0, 0, 299, 297, 1, 0, 0, 0, 300, 303, 3, 32, 16, 0, 301, 303, 3, 30, 15, 0, 302, 300, 1, 0, 0, 0, 302, 301, 1, 0, 0, 0, 303, 29, 1, 0, 0, 0, 304, 305, 5, 52, 0, 0, 305, 31, 1, 0, 0, 0, 306, 307, 3, 34, 17, 0, 307, 308, 5, 11, 0, 0, 308, 309, 3, 36, 18, 0, 309, 33, 1, 0, 0, 0, 310, 311, 5, 52, 0, 0, 311, 35, 1, 0, 0, 0, 312, 313, 5, 52, 0, 0, 313, 37, 1, 0, 0, 0, 314, 316, 5, 51, 0, 0, 315, 314, 1, 0, 0, 0, 315, 316, 1, 0, 0, 0, 316, 317, 1, 0, 0, 0, 317, 318, 5, 12, 0, 0, 318, 319, 3, 40, 20, 0, 319, 39, 1, 0, 0, 0, 320, 322, 5, 52, 0, 0, 321, 323, 3, 42, 21, 0, 322, 321, 1, 0, 0, 0, 322, 323, 1, 0, 0, 0, 323, 325, 1, 0, 0, 0, 324, 326, 3, 48, 24, 0, 325, 324, 1, 0, 0, 0, 325, 326, 1, 0, 0, 0, 326, 328, 1, 0, 0, 0, 327, 329, 5, 50, 0, 0, 328, 327, 1, 0, 0, 0, 328, 329, 1, 0, 0, 0, 329, 41, 1, 0, 0, 0, 330, 334, 5, 13, 0, 0, 331, 333, 5, 57, 0, 0, 332, 331, 1, 0, 0, 0, 333, 336, 1, 0, 0, 0, 334, 332, 1, 0, 0, 0, 334, 335, 1, 0, 0, 0, 335, 338, 1, 0, 0, 0, 336, 334, 1, 0, 0, 0, 337, 339, 3, 44, 22, 0, 338, 337, 1, 0, 0, 0, 338, 339, 1, 0, 0, 0, 339, 340, 1, 0, 0, 0, 340, 341, 5, 14, 0, 0, 341, 43, 1, 0, 0, 0, 342, 353, 3, 46, 23, 0, 343, 347, 5, 3, 0, 0, 344, 346, 5, 57, 0, 0, 345, 344, 1, 0, 0, 0, 346, 349, 1, 0, 0, 0, 347, 345, 1, 0, 0, 0, 347, 348, 1, 0, 0, 0, 348, 350, 1, 0, 0, 0, 349, 347, 1, 0, 0, 0, 350, 352, 3, 46, 23, 0, 351, 343, 1, 0, 0, 0, 352, 355, 1, 0, 0, 0, 353, 351, 1, 0, 0, 0, 353, 354, 1, 0, 0, 0, 354, 45, 1, 0, 0, 0, 355, 353, 1, 0, 0, 0, 356, 358, 5, 52, 0, 0, 357, 359, 3, 48, 24, 0, 358, 357, 1, 0, 0, 0, 358, 359, 1, 0, 0, 0, 359, 363, 1, 0, 0, 0, 360, 362, 5, 57, 0, 0, 361, 360, 1, 0, 0, 0, 362, 365, 1, 0, 0, 0, 363, 361, 1, 0, 0, 0, 363, 364, 1, 0, 0, 0, 364, 47, 1, 0, 0, 0, 365, 363, 1, 0, 0, 0, 366, 370, 3, 50, 25, 0, 367, 370, 3, 54, 27, 0, 368, 370, 3, 64, 32, 0, 369, 366, 1, 0, 0, 0, 369, 367, 1, 0, 0, 0, 369, 368, 1, 0, 0, 0, 370, 49, 1, 0, 0, 0, 371, 373, 3, 28, 14, 0, 372, 374, 3, 52, 26, 0, 373, 372, 1, 0, 0, 0, 373, 374, 1, 0, 0, 0, 374, 51, 1, 0, 0, 0, 375, 379, 5, 13, 0, 0, 376, 378, 5, 57, 0, 0, 377, 376, 1, 0, 0, 0, 378, 381, 1, 0, 0, 0, 379, 377, 1, 0, 0, 0, 379, 380, 1, 0, 0, 0, 380, 382, 1, 0, 0, 0, 381, 379, 1, 0, 0, 0, 382, 393, 3, 48, 24, 0, 383, 387, 5, 3, 0, 0, 384, 386, 5, 57, 0, 0, 385, 384, 1, 0, 0, 0, 386, 389, 1, 0, 0, 0, 387, 385, 1, 0, 0, 0, 387, 388, 1, 0, 0, 0, 388, 390, 1, 0, 0, 0, 389, 387, 1, 0, 0, 0, 390, 392, 3, 48, 24, 0, 391, 383, 1, 0, 0, 0, 392, 395, 1, 0, 0, 0, 393, 391, 1, 0, 0, 0, 393, 394, 1, 0, 0, 0, 394, 399, 1, 0, 0, 0, 395, 393, 1, 0, 0, 0, 396, 398, 5, 57, 0, 0, 397, 396, 1, 0, 0, 0, 398, 401, 1, 0, 0, 0, 399, 397, 1, 0, 0, 0, 399, 400, 1, 0, 0, 0, 400, 402, 1, 0, 0, 0, 401, 399, 1, 0, 0, 0, 402, 403, 5, 14, 0, 0, 403, 53, 1, 0, 0, 0, 404, 407, 3, 56, 28, 0, 405, 407, 3, 58, 29, 0, 406, 404, 1, 0, 0, 0, 406, 405, 1, 0, 0, 0, 407, 55, 1, 0, 0, 0, 408, 412, 5, 15, 0, 0, 409, 411, 5, 57, 0, 0, 410, 409, 1, 0, 0, 0, 411, 414, 1, 0, 0, 0, 412, 410, 1, 0, 0, 0, 412, 413, 1, 0, 0, 0, 413, 415, 1, 0, 0, 0, 414, 412, 1, 0, 0, 0, 415, 419, 5, 6, 0, 0, 416, 418, 5, 57, 0, 0, 417, 416, 1, 0, 0, 0, 418, 421, 1, 0, 0, 0, 419, 417, 1, 0, 0, 0, 419, 420, 1, 0, 0, 0, 420, 422, 1, 0, 0, 0, 421, 419, 1, 0, 0, 0, 422, 433, 5, 52, 0, 0, 423, 427, 5, 3, 0, 0, 424, 426, 5, 57, 0, 0, 425, 424, 1, 0, 0, 0, 426, 429, 1, 0, 0, 0, 427, 425, 1, 0, 0, 0, 427, 428, 1, 0, 0, 0, 428, 430, 1, 0, 0, 0, 429, 427, 1, 0, 0, 0, 430, 432, 5, 52, 0, 0, 431, 423, 1, 0, 0, 0, 432, 435, 1, 0, 0, 0, 433, 431, 1, 0, 0, 0, 433, 434, 1, 0, 0, 0, 434, 439, 1, 0, 0, 0, 435, 433, 1, 0, 0, 0, 436, 438, 5, 57, 0, 0, 437, 436, 1, 0, 0, 0, 438, 441, 1, 0, 0, 0, 439, 437, 1, 0, 0, 0, 439, 440, 1, 0, 0, 0, 440, 442, 1, 0, 0, 0, 441, 439, 1, 0, 0, 0, 442, 443, 5, 7, 0, 0, 443, 57, 1, 0, 0, 0, 444, 448, 5, 16, 0, 0, 445, 447, 5, 57, 0, 0, 446, 445, 1, 0, 0, 0, 447, 450, 1, 0, 0, 0, 448, 446, 1, 0, 0, 0, 448, 449, 1, 0, 0, 0, 449, 451, 1, 0, 0, 0, 450, 448, 1, 0, 0, 0, 451, 455, 5, 6, 0, 0, 452, 454, 5, 57, 0, 0, 453, 452, 1, 0, 0, 0, 454, 457, 1, 0, 0, 0, 455, 453, 1, 0, 0, 0, 455, 456, 1, 0, 0, 0, 456, 459, 1, 0, 0, 0, 457, 455, 1, 0, 0, 0, 458, 460, 3, 60, 30, 0, 459, 458, 1, 0, 0, 0, 459, 460, 1, 0, 0, 0, 460, 461, 1, 0, 0, 0, 461, 462, 5, 7, 0, 0, 462, 59, 1, 0, 0, 0, 463, 472, 3, 62, 31, 0, 464, 466, 5, 57, 0, 0, 465, 464, 1, 0, 0, 0, 466, 467, 1, 0, 0, 0, 467, 465, 1, 0, 0, 0, 467, 468, 1, 0, 0, 0, 468, 469, 1, 0, 0, 0, 469, 471, 3, 62, 31, 0, 470, 465, 1, 0, 0, 0, 471, 474, 1, 0, 0, 0, 472, 470, 1, 0, 0, 0, 472, 473, 1, 0, 0, 0, 473, 61, 1, 0, 0, 0, 474, 472, 1, 0, 0, 0, 475, 476, 5, 52, 0, 0, 476, 480, 3, 48, 24, 0, 477, 479, 5, 57, 0, 0, 478, 477, 1, 0, 0, 0, 479, 482, 1, 0, 0, 0, 480, 478, 1, 0, 0, 0, 480, 481, 1, 0, 0, 0, 481, 63, 1, 0, 0, 0, 482, 480, 1, 0, 0, 0, 483, 498, 3, 66, 33, 0, 484, 486, 5, 57, 0, 0, 485, 484, 1, 0, 0, 0, 486, 489, 1, 0, 0, 0, 487, 485, 1, 0, 0, 0, 487, 488, 1, 0, 0, 0, 488, 490, 1, 0, 0, 0, 489, 487, 1, 0, 0, 0, 490, 494, 5, 17, 0, 0, 491, 493, 5, 57, 0, 0, 492, 491, 1, 0, 0, 0, 493, 496, 1, 0, 0, 0, 494, 492, 1, 0, 0, 0, 494, 495, 1, 0, 0, 0, 495, 497, 1, 0, 0, 0, 496, 494, 1, 0, 0, 0, 497, 499, 3, 66, 33, 0, 498, 487, 1, 0, 0, 0, 499, 500, 1, 0, 0, 0, 500, 498, 1, 0, 0, 0, 500, 501, 1, 0, 0, 0, 501, 65, 1, 0, 0, 0, 502, 505, 3, 50, 25, 0, 503, 505, 3, 54, 27, 0, 504, 502, 1, 0, 0, 0, 504, 503, 1, 0, 0, 0, 505, 67, 1, 0, 0, 0, 506, 508, 5, 51, 0, 0, 507, 506, 1, 0, 0, 0, 507, 508, 1, 0, 0, 0, 508, 509, 1, 0, 0, 0, 509, 510, 5, 18, 0, 0, 510, 511, 3, 70, 35, 0, 511, 69, 1, 0, 0, 0, 512, 514, 5, 52, 0, 0, 513, 515, 3, 42, 21, 0, 514, 513, 1, 0, 0, 0, 514, 515, 1, 0, 0, 0, 515, 516, 1, 0, 0, 0, 516, 517, 3, 72, 36, 0, 517, 521, 3, 74, 37, 0, 518, 520, 5, 57, 0, 0, 519, 518, 1, 0, 0, 0, 520, 523, 1, 0, 0, 0, 521, 519, 1, 0, 0, 0, 521, 522, 1, 0, 0, 0, 522, 71, 1, 0, 0, 0, 523, 521, 1, 0, 0, 0, 524, 525, 3, 76, 38, 0, 525, 73, 1, 0, 0, 0, 526, 527, 3, 76, 38, 0, 527, 75, 1, 0, 0, 0, 528, 546, 5, 2, 0, 0, 529, 531, 5, 57, 0, 0, 530, 529, 1, 0, 0, 0, 531, 534, 1, 0, 0, 0, 532, 530, 1, 0, 0, 0, 532, 533, 1, 0, 0, 0, 533, 547, 1, 0, 0, 0, 534, 532, 1, 0, 0, 0, 535, 537, 3, 78, 39, 0, 536, 535, 1, 0, 0, 0, 536, 537, 1, 0, 0, 0, 537, 547, 1, 0, 0, 0, 538, 543, 3, 78, 39, 0, 539, 540, 5, 3, 0, 0, 540, 542, 3, 78, 39, 0, 541, 539, 1, 0, 0, 0, 542, 545, 1, 0, 0, 0, 543, 541, 1, 0, 0, 0, 543, 544, 1, 0, 0, 0, 544, 547, 1, 0, 0, 0, 545, 543, 1, 0, 0, 0, 546, 532, 1, 0, 0, 0, 546, 536, 1, 0, 0, 0, 546, 538, 1, 0, 0, 0, 547, 548, 1, 0, 0, 0, 548, 549, 5, 4, 0, 0, 549, 77, 1, 0, 0, 0, 550, 553, 3, 80, 40, 0, 551, 553, 3, 82, 41, 0, 552, 550, 1, 0, 0, 0, 552, 551, 1, 0, 0, 0, 553, 79, 1, 0, 0, 0, 554, 556, 5, 57, 0, 0, 555, 554, 1, 0, 0, 0, 556, 559, 1, 0, 0, 0, 557, 555, 1, 0, 0, 0, 557, 558, 1, 0, 0, 0, 558, 560, 1, 0, 0, 0, 559, 557, 1, 0, 0, 0, 560, 562, 5, 52, 0, 0, 561, 563, 3, 48, 24, 0, 562, 561, 1, 0, 0, 0, 562, 563, 1, 0, 0, 0, 563, 567, 1, 0, 0, 0, 564, 566, 5, 57, 0, 0, 565, 564, 1, 0, 0, 0, 566, 569, 1, 0, 0, 0, 567, 565, 1, 0, 0, 0, 567, 568, 1, 0, 0, 0, 568, 81, 1, 0, 0, 0, 569, 567, 1, 0, 0, 0, 570, 572, 5, 57, 0, 0, 571, 570, 1, 0, 0, 0, 572, 575, 1, 0, 0, 0, 573, 571, 1, 0, 0, 0, 573, 574, 1, 0, 0, 0, 574, 576, 1, 0, 0, 0, 575, 573, 1, 0, 0, 0, 576, 577, 5, 19, 0, 0, 577, 578, 5, 52, 0, 0, 578, 580, 5, 20, 0, 0, 579, 581, 3, 48, 24, 0, 580, 579, 1, 0, 0, 0, 580, 581, 1, 0, 0, 0, 581, 585, 1, 0, 0, 0, 582, 584, 5, 57, 0, 0, 583, 582, 1, 0, 0, 0, 584, 587, 1, 0, 0, 0, 585, 583, 1, 0, 0, 0, 585, 586, 1, 0, 0, 0, 586, 83, 1, 0, 0, 0, 587, 585, 1, 0, 0, 0, 588, 590, 5, 51, 0, 0, 589, 588, 1, 0, 0, 0, 589, 590, 1, 0, 0, 0, 590, 591, 1, 0, 0, 0, 591, 592, 5, 21, 0, 0, 592, 593, 3, 86, 43, 0, 593, 85, 1, 0, 0, 0, 594, 595, 5, 52, 0, 0, 595, 596, 3, 48, 24, 0, 596, 599, 5, 22, 0, 0, 597, 600, 3, 28, 14, 0, 598, 600, 3, 88, 44, 0, 599, 597, 1, 0, 0, 0, 599, 598, 1, 0, 0, 0, 600, 604, 1, 0, 0, 0, 601, 603, 5, 57, 0, 0, 602, 601, 1, 0, 0, 0, 603, 606, 1, 0, 0, 0, 604, 602, 1, 0, 0, 0, 604, 605, 1, 0, 0, 0, 605, 87, 1, 0, 0, 0, 606, 604, 1, 0, 0, 0, 607, 621, 3, 92, 46, 0, 608, 610, 5, 54, 0, 0, 609, 608, 1, 0, 0, 0, 609, 610, 1, 0, 0, 0, 610, 611, 1, 0, 0, 0, 611, 621, 5, 53, 0, 0, 612, 614, 5, 54, 0, 0, 613, 612, 1, 0, 0, 0, 613, 614, 1, 0, 0, 0, 614, 615, 1, 0, 0, 0, 615, 621, 5, 55, 0, 0, 616, 621, 5, 56, 0, 0, 617, 621, 3, 94, 47, 0, 618, 621, 3, 96, 48, 0, 619, 621, 3, 102, 51, 0, 620, 607, 1, 0, 0, 0, 620, 609, 1, 0, 0, 0, 620, 613, 1, 0, 0, 0, 620, 616, 1, 0, 0, 0, 620, 617, 1, 0, 0, 0, 620, 618, 1, 0, 0, 0, 620, 619, 1, 0, 0, 0, 621, 89, 1, 0, 0, 0, 622, 634, 3, 92, 46, 0, 623, 625, 5, 54, 0, 0, 624, 623, 1, 0, 0, 0, 624, 625, 1, 0, 0, 0, 625, 626, 1, 0, 0, 0, 626, 634, 5, 53, 0, 0, 627, 629, 5, 54, 0, 0, 628, 627, 1, 0, 0, 0, 628, 629, 1, 0, 0, 0, 629, 630, 1, 0, 0, 0, 630, 634, 5, 55, 0, 0, 631, 634, 5, 56, 0, 0, 632, 634, 3, 94, 47, 0, 633, 622, 1, 0, 0, 0, 633, 624, 1, 0, 0, 0, 633, 628, 1, 0, 0, 0, 633, 631, 1, 0, 0, 0, 633, 632, 1, 0, 0, 0, 634, 91, 1, 0, 0, 0, 635, 636, 7, 1, 0, 0, 636, 93, 1, 0, 0, 0, 637, 638, 3, 28, 14, 0, 638, 639, 5, 25, 0, 0, 639, 640, 5, 52, 0, 0, 640, 95, 1, 0, 0, 0, 641, 645, 5, 19, 0, 0, 642, 644, 5, 57, 0, 0, 643, 642, 1, 0, 0, 0, 644, 647, 1, 0, 0, 0, 645, 643, 1, 0, 0, 0, 645, 646, 1, 0, 0, 0, 646, 649, 1, 0, 0, 0, 647, 645, 1, 0, 0, 0, 648, 650, 3, 98, 49, 0, 649, 648, 1, 0, 0, 0, 649, 650, 1, 0, 0, 0, 650, 651, 1, 0, 0, 0, 651, 652, 5, 20, 0, 0, 652, 97, 1, 0, 0, 0, 653, 675, 3, 100, 50, 0, 654, 671, 3, 100, 50, 0, 655, 659, 5, 3, 0, 0, 656, 658, 5, 57, 0, 0, 657, 656, 1, 0, 0, 0, 658, 661, 1, 0, 0, 0, 659, 657, 1, 0, 0, 0, 659, 660, 1, 0, 0, 0, 660, 662, 1, 0, 0, 0, 661, 659, 1, 0, 0, 0, 662, 666, 3, 100, 50, 0, 663, 665, 5, 57, 0, 0, 664, 663, 1, 0, 0, 0, 665, 668, 1, 0, 0, 0, 666, 664, 1, 0, 0, 0, 666, 667, 1, 0, 0, 0, 667, 670, 1, 0, 0, 0, 668, 666, 1, 0, 0, 0, 669, 655, 1, 0, 0, 0, 670, 673, 1, 0, 0, 0, 671, 669, 1, 0, 0, 0, 671, 672, 1, 0, 0, 0, 672, 675, 1, 0, 0, 0, 673, 671, 1, 0, 0, 0, 674, 653, 1, 0, 0, 0, 674, 654, 1, 0, 0, 0, 675, 99, 1, 0, 0, 0, 676, 679, 3, 28, 14, 0, 677, 679, 3, 88, 44, 0, 678, 676, 1, 0, 0, 0, 678, 677, 1, 0, 0, 0, 679, 101, 1, 0, 0, 0, 680, 684, 5, 6, 0, 0, 681, 683, 5, 57, 0, 0, 682, 681, 1, 0, 0, 0, 683, 686, 1, 0, 0, 0, 684, 682, 1, 0, 0, 0, 684, 685, 1, 0, 0, 0, 685, 688, 1, 0, 0, 0, 686, 684, 1, 0, 0, 0, 687, 689, 3, 104, 52, 0, 688, 687, 1, 0, 0, 0, 688, 689, 1, 0, 0, 0, 689, 690, 1, 0, 0, 0, 690, 691, 5, 7, 0, 0, 691, 103, 1, 0, 0, 0, 692, 703, 3, 106, 53, 0, 693, 697, 5, 3, 0, 0, 694, 696, 5, 57, 0, 0, 695, 694, 1, 0, 0, 0, 696, 699, 1, 0, 0, 0, 697, 695, 1, 0, 0, 0, 697, 698, 1, 0, 0, 0, 698, 700, 1, 0, 0, 0, 699, 697, 1, 0, 0, 0, 700, 702, 3, 106, 53, 0, 701, 693, 1, 0, 0, 0, 702, 705, 1, 0, 0, 0, 703, 701, 1, 0, 0, 0, 703, 704, 1, 0, 0, 0, 704, 105, 1, 0, 0, 0, 705, 703, 1, 0, 0, 0, 706, 707, 5, 52, 0, 0, 707, 708, 5, 8, 0, 0, 708, 712, 3, 100, 50, 0, 709, 711, 5, 57, 0, 0, 710, 709, 1, 0, 0, 0, 711, 714, 1, 0, 0, 0, 712, 710, 1, 0, 0, 0, 712, 713, 1, 0, 0, 0, 713, 107, 1, 0, 0, 0, 714, 712, 1, 0, 0, 0, 715, 717, 3, 4, 2, 0, 716, 715, 1, 0, 0, 0, 716, 717, 1, 0, 0, 0, 717, 719, 1, 0, 0, 0, 718, 720, 5, 51, 0, 0, 719, 718, 1, 0, 0, 0, 719, 720, 1, 0, 0, 0, 720, 721, 1, 0, 0, 0, 721, 722, 5, 26, 0, 0, 722, 723, 3, 110, 55, 0, 723, 109, 1, 0, 0, 0, 724, 726, 3, 70, 35, 0, 725, 727, 3, 112, 56, 0, 726, 725, 1, 0, 0, 0, 726, 727, 1, 0, 0, 0, 727, 731, 1, 0, 0, 0, 728, 730, 5, 57, 0, 0, 729, 728, 1, 0, 0, 0, 730, 733, 1, 0, 0, 0, 731, 729, 1, 0, 0, 0, 731, 732, 1, 0, 0, 0, 732, 111, 1, 0, 0, 0, 733, 731, 1, 0, 0, 0, 734, 738, 5, 6, 0, 0, 735, 737, 5, 57, 0, 0, 736, 735, 1, 0, 0, 0, 737, 740, 1, 0, 0, 0, 738, 736, 1, 0, 0, 0, 738, 739, 1, 0, 0, 0, 739, 750, 1, 0, 0, 0, 740, 738, 1, 0, 0, 0, 741, 745, 5, 50, 0, 0, 742, 744, 5, 57, 0, 0, 743, 742, 1, 0, 0, 0, 744, 747, 1, 0, 0, 0, 745, 743, 1, 0, 0, 0, 745, 746, 1, 0, 0, 0, 746, 749, 1, 0, 0, 0, 747, 745, 1, 0, 0, 0, 748, 741, 1, 0, 0, 0, 749, 752, 1, 0, 0, 0, 750, 748, 1, 0, 0, 0, 750, 751, 1, 0, 0, 0, 751, 760, 1, 0, 0, 0, 752, 750, 1, 0, 0, 0, 753, 757, 3, 114, 57, 0, 754, 756, 5, 57, 0, 0, 755, 754, 1, 0, 0, 0, 756, 759, 1, 0, 0, 0, 757, 755, 1, 0, 0, 0, 757, 758, 1, 0, 0, 0, 758, 761, 1, 0, 0, 0, 759, 757, 1, 0, 0, 0, 760, 753, 1, 0, 0, 0, 760, 761, 1, 0, 0, 0, 761, 771, 1, 0, 0, 0, 762, 766, 5, 50, 0, 0, 763, 765, 5, 57, 0, 0, 764, 763, 1, 0, 0, 0, 765, 768, 1, 0, 0, 0, 766, 764, 1, 0, 0, 0, 766, 767, 1, 0, 0, 0, 767, 770, 1, 0, 0, 0, 768, 766, 1, 0, 0, 0, 769, 762, 1, 0, 0, 0, 770, 773, 1, 0, 0, 0, 771, 769, 1, 0, 0, 0, 771, 772, 1, 0, 0, 0, 772, 781, 1, 0, 0, 0, 773, 771, 1, 0, 0, 0, 774, 778, 3, 126, 63, 0, 775, 777, 5, 57, 0, 0, 776, 775, 1, 0, 0, 0, 777, 780, 1, 0, 0, 0, 778, 776, 1, 0, 0, 0, 778, 779, 1, 0, 0, 0, 779, 782, 1, 0, 0, 0, 780, 778, 1, 0, 0, 0, 781, 774, 1, 0, 0, 0, 781, 782, 1, 0, 0, 0, 782, 792, 1, 0, 0, 0, 783, 787, 5, 50, 0, 0, 784, 786, 5, 57, 0, 0, 785, 784, 1, 0, 0, 0, 786, 789, 1, 0, 0, 0, 787, 785, 1, 0, 0, 0, 787, 788, 1, 0, 0, 0, 788, 791, 1, 0, 0, 0, 789, 787, 1, 0, 0, 0, 790, 783, 1, 0, 0, 0, 791, 794, 1, 0, 0, 0, 792, 790, 1, 0, 0, 0, 792, 793, 1, 0, 0, 0, 793, 795, 1, 0, 0, 0, 794, 792, 1, 0, 0, 0, 795, 796, 5, 7, 0, 0, 796, 113, 1, 0, 0, 0, 797, 799, 3, 116, 58, 0, 798, 800, 5, 57, 0, 0, 799, 798, 1, 0, 0, 0, 800, 801, 1, 0, 0, 0, 801, 799, 1, 0, 0, 0, 801, 802, 1, 0, 0, 0, 802, 803, 1, 0, 0, 0, 803, 804, 5, 27, 0, 0, 804, 115, 1, 0, 0, 0, 805, 807, 3, 118, 59, 0, 806, 808, 5, 3, 0, 0, 807, 806, 1, 0, 0, 0, 807, 808, 1, 0, 0, 0, 808, 811, 1, 0, 0, 0, 809, 811, 5, 50, 0, 0, 810, 805, 1, 0, 0, 0, 810, 809, 1, 0, 0, 0, 811, 815, 1, 0, 0, 0, 812, 814, 5, 57, 0, 0, 813, 812, 1, 0, 0, 0, 814, 817, 1, 0, 0, 0, 815, 813, 1, 0, 0, 0, 815, 816, 1, 0, 0, 0, 816, 819, 1, 0, 0, 0, 817, 815, 1, 0, 0, 0, 818, 810, 1, 0, 0, 0, 819, 820, 1, 0, 0, 0, 820, 818, 1, 0, 0, 0, 820, 821, 1, 0, 0, 0, 821, 117, 1, 0, 0, 0, 822, 824, 3, 4, 2, 0, 823, 822, 1, 0, 0, 0, 823, 824, 1, 0, 0, 0, 824, 826, 1, 0, 0, 0, 825, 827, 5, 52, 0, 0, 826, 825, 1, 0, 0, 0, 826, 827, 1, 0, 0, 0, 827, 828, 1, 0, 0, 0, 828, 829, 3, 120, 60, 0, 829, 119, 1, 0, 0, 0, 830, 834, 3, 28, 14, 0, 831, 833, 5, 57, 0, 0, 832, 831, 1, 0, 0, 0, 833, 836, 1, 0, 0, 0, 834, 832, 1, 0, 0, 0, 834, 835, 1, 0, 0, 0, 835, 838, 1, 0, 0, 0, 836, 834, 1, 0, 0, 0, 837, 839, 3, 52, 26, 0, 838, 837, 1, 0, 0, 0, 838, 839, 1, 0, 0, 0, 839, 843, 1, 0, 0, 0, 840, 842, 5, 57, 0, 0, 841, 840, 1, 0, 0, 0, 842, 845, 1, 0, 0, 0, 843, 841, 1, 0, 0, 0, 843, 844, 1, 0, 0, 0, 844, 847, 1, 0, 0, 0, 845, 843, 1, 0, 0, 0, 846, 848, 3, 124, 62, 0, 847, 846, 1, 0, 0, 0, 847, 848, 1, 0, 0, 0, 848, 850, 1, 0, 0, 0, 849, 851, 3, 122, 61, 0, 850, 849, 1, 0, 0, 0, 850, 851, 1, 0, 0, 0, 851, 121, 1, 0, 0, 0, 852, 853, 5, 28, 0, 0, 853, 123, 1, 0, 0, 0, 854, 858, 5, 6, 0, 0, 855, 857, 5, 57, 0, 0, 856, 855, 1, 0, 0, 0, 857, 860, 1, 0, 0, 0, 858, 856, 1, 0, 0, 0, 858, 859, 1, 0, 0, 0, 859, 861, 1, 0, 0, 0, 860, 858, 1, 0, 0, 0, 861, 862, 3, 116, 58, 0, 862, 863, 5, 7, 0, 0, 863, 125, 1, 0, 0, 0, 864, 867, 3, 128, 64, 0, 865, 867, 5, 50, 0, 0, 866, 864, 1, 0, 0, 0, 866, 865, 1, 0, 0, 0, 867, 880, 1, 0, 0, 0, 868, 870, 5, 57, 0, 0, 869, 868, 1, 0, 0, 0, 870, 873, 1, 0, 0, 0, 871, 869, 1, 0, 0, 0, 871, 872, 1, 0, 0, 0, 872, 876, 1, 0, 0, 0, 873, 871, 1, 0, 0, 0, 874, 877, 3, 128, 64, 0, 875, 877, 5, 50, 0, 0, 876, 874, 1, 0, 0, 0, 876, 875, 1, 0, 0, 0, 877, 879, 1, 0, 0, 0, 878, 871, 1, 0, 0, 0, 879, 882, 1, 0, 0, 0, 880, 878, 1, 0, 0, 0, 880, 881, 1, 0, 0, 0, 881, 127, 1, 0, 0, 0, 882, 880, 1, 0, 0, 0, 883, 886, 3, 130, 65, 0, 884, 886, 3, 136, 68, 0, 885, 883, 1, 0, 0, 0, 885, 884, 1, 0, 0, 0, 886, 129, 1, 0, 0, 0, 887, 888, 3, 132, 66, 0, 888, 889, 5, 29, 0, 0, 889, 890, 3, 150, 75, 0, 890, 131, 1, 0, 0, 0, 891, 894, 3, 138, 69, 0, 892, 894, 3, 134, 67, 0, 893, 891, 1, 0, 0, 0, 893, 892, 1, 0, 0, 0, 894, 133, 1, 0, 0, 0, 895, 899, 5, 19, 0, 0, 896, 898, 5, 57, 0, 0, 897, 896, 1, 0, 0, 0, 898, 901, 1, 0, 0, 0, 899, 897, 1, 0, 0, 0, 899, 900, 1, 0, 0, 0, 900, 902, 1, 0, 0, 0, 901, 899, 1, 0, 0, 0, 902, 919, 3, 138, 69, 0, 903, 907, 5, 3, 0, 0, 904, 906, 5, 57, 0, 0, 905, 904, 1, 0, 0, 0, 906, 909, 1, 0, 0, 0, 907, 905, 1, 0, 0, 0, 907, 908, 1, 0, 0, 0, 908, 910, 1, 0, 0, 0, 909, 907, 1, 0, 0, 0, 910, 914, 3, 138, 69, 0, 911, 913, 5, 57, 0, 0, 912, 911, 1, 0, 0, 0, 913, 916, 1, 0, 0, 0, 914, 912, 1, 0, 0, 0, 914, 915, 1, 0, 0, 0, 915, 918, 1, 0, 0, 0, 916, 914, 1, 0, 0, 0, 917, 903, 1, 0, 0, 0, 918, 921, 1, 0, 0, 0, 919, 917, 1, 0, 0, 0, 919, 920, 1, 0, 0, 0, 920, 922, 1, 0, 0, 0, 921, 919, 1, 0, 0, 0, 922, 923, 5, 20, 0, 0, 923, 135, 1, 0, 0, 0, 924, 925, 3, 168, 84, 0, 925, 926, 5, 30, 0, 0, 926, 927, 3, 168, 84, 0, 927, 137, 1, 0, 0, 0, 928, 937, 3, 162, 81, 0, 929, 937, 3, 156, 78, 0, 930, 937, 3, 90, 45, 0, 931, 937, 3, 158, 79, 0, 932, 937, 3, 178, 89, 0, 933, 937, 3, 140, 70, 0, 934, 937, 3, 146, 73, 0, 935, 937, 3, 144, 72, 0, 936, 928, 1, 0, 0, 0, 936, 929, 1, 0, 0, 0, 936, 930, 1, 0, 0, 0, 936, 931, 1, 0, 0, 0, 936, 932, 1, 0, 0, 0, 936, 933, 1, 0, 0, 0, 936, 934, 1, 0, 0, 0, 936, 935, 1, 0, 0, 0, 937, 139, 1, 0, 0, 0, 938, 939, 3, 142, 71, 0, 939, 940, 3, 138, 69, 0, 940, 141, 1, 0, 0, 0, 941, 942, 7, 2, 0, 0, 942, 143, 1, 0, 0, 0, 943, 944, 5, 2, 0, 0, 944, 945, 3, 138, 69, 0, 945, 946, 5, 28, 0, 0, 946, 947, 3, 138, 69, 0, 947, 948, 5, 8, 0, 0, 948, 949, 3, 138, 69, 0, 949, 950, 5, 4, 0, 0, 950, 145, 1, 0, 0, 0, 951, 952, 5, 2, 0, 0, 952, 953, 3, 138, 69, 0, 953, 954, 3, 148, 74, 0, 954, 955, 3, 138, 69, 0, 955, 956, 5, 4, 0, 0, 956, 147, 1, 0, 0, 0, 957, 958, 7, 3, 0, 0, 958, 149, 1, 0, 0, 0, 959, 962, 3, 180, 90, 0, 960, 962, 3, 182, 91, 0, 961, 959, 1, 0, 0, 0, 961, 960, 1, 0, 0, 0, 962, 151, 1, 0, 0, 0, 963, 964, 3, 130, 65, 0, 964, 153, 1, 0, 0, 0, 965, 969, 5, 6, 0, 0, 966, 968, 5, 57, 0, 0, 967, 966, 1, 0, 0, 0, 968, 971, 1, 0, 0, 0, 969, 967, 1, 0, 0, 0, 969, 970, 1, 0, 0, 0, 970, 972, 1, 0, 0, 0, 971, 969, 1, 0, 0, 0, 972, 976, 3, 128, 64, 0, 973, 975, 5, 57, 0, 0, 974, 973, 1, 0, 0, 0, 975, 978, 1, 0, 0, 0, 976, 974, 1, 0, 0, 0, 976, 977, 1, 0, 0, 0, 977, 979, 1, 0, 0, 0, 978, 976, 1, 0, 0, 0, 979, 980, 5, 7, 0, 0, 980, 155, 1, 0, 0, 0, 981, 982, 5, 46, 0, 0, 982, 983, 3, 28, 14, 0, 983, 157, 1, 0, 0, 0, 984, 985, 3, 160, 80, 0, 985, 986, 5, 47, 0, 0, 986, 987, 3, 160, 80, 0, 987, 159, 1, 0, 0, 0, 988, 990, 5, 54, 0, 0, 989, 988, 1, 0, 0, 0, 989, 990, 1, 0, 0, 0, 990, 991, 1, 0, 0, 0, 991, 992, 5, 53, 0, 0, 992, 161, 1, 0, 0, 0, 993, 998, 3, 168, 84, 0, 994, 998, 3, 170, 85, 0, 995, 998, 3, 164, 82, 0, 996, 998, 3, 166, 83, 0, 997, 993, 1, 0, 0, 0, 997, 994, 1, 0, 0, 0, 997, 995, 1, 0, 0, 0, 997, 996, 1, 0, 0, 0, 998, 163, 1, 0, 0, 0, 999, 1000, 3, 172, 86, 0, 1000, 165, 1, 0, 0, 0, 1001, 1002, 3, 172, 86, 0, 1002, 1003, 3, 176, 88, 0, 1003, 167, 1, 0, 0, 0, 1004, 1006, 3, 172, 86, 0, 1005, 1004, 1, 0, 0, 0, 1005, 1006, 1, 0, 0, 0, 1006, 1007, 1, 0, 0, 0, 1007, 1008, 5, 8, 0, 0, 1008, 1009, 3, 174, 87, 0, 1009, 169, 1, 0, 0, 0, 1010, 1012, 3, 172, 86, 0, 1011, 1010, 1, 0, 0, 0, 1011, 1012, 1, 0, 0, 0, 1012, 1013, 1, 0, 0, 0, 1013, 1014, 5, 8, 0, 0, 1014, 1015, 3, 174, 87, 0, 1015, 1016, 3, 176, 88, 0, 1016, 171, 1, 0, 0, 0, 1017, 1018, 5, 52, 0, 0, 1018, 173, 1, 0, 0, 0, 1019, 1020, 5, 52, 0, 0, 1020, 175, 1, 0, 0, 0, 1021, 1022, 5, 19, 0, 0, 1022, 1023, 5, 53, 0, 0, 1023, 1024, 5, 20, 0, 0, 1024, 177, 1, 0, 0, 0, 1025, 1026, 5, 11, 0, 0, 1026, 1031, 5, 52, 0, 0, 1027, 1028, 5, 11, 0, 0, 1028, 1030, 5, 52, 0, 0, 1029, 1027, 1, 0, 0, 0, 1030, 1033, 1, 0, 0, 0, 1031, 1029, 1, 0, 0, 0, 1031, 1032, 1, 0, 0, 0, 1032, 179, 1, 0, 0, 0, 1033, 1031, 1, 0, 0, 0, 1034, 1039, 3, 152, 76, 0, 1035, 1039, 3, 162, 81, 0, 1036, 1039, 3, 154, 77, 0, 1037, 1039, 3, 184, 92, 0, 1038, 1034, 1, 0, 0, 0, 1038, 1035, 1, 0, 0, 0, 1038, 1036, 1, 0, 0, 0, 1038, 1037, 1, 0, 0, 0, 1039, 181, 1, 0, 0, 0, 1040, 1044, 5, 19, 0, 0, 1041, 1043, 5, 57, 0, 0, 1042, 1041, 1, 0, 0, 0, 1043, 1046, 1, 0, 0, 0, 1044, 1042, 1, 0, 0, 0, 1044, 1045, 1, 0, 0, 0, 1045, 1047, 1, 0, 0, 0, 1046, 1044, 1, 0, 0, 0, 1047, 1064, 3, 180, 90, 0, 1048, 1052, 5, 3, 0, 0, 1049, 1051, 5, 57, 0, 0, 1050, 1049, 1, 0, 0, 0, 1051, 1054, 1, 0, 0, 0, 1052, 1050, 1, 0, 0, 0, 1052, 1053, 1, 0, 0, 0, 1053, 1055, 1, 0, 0, 0, 1054, 1052, 1, 0, 0, 0, 1055, 1059, 3, 180, 90, 0, 1056, 1058, 5, 57, 0, 0, 1057, 1056, 1, 0, 0, 0, 1058, 1061, 1, 0, 0, 0, 1059, 1057, 1, 0, 0, 0, 1059, 1060, 1, 0, 0, 0, 1060, 1063, 1, 0, 0, 0, 1061, 1059, 1, 0, 0, 0, 1062, 1048, 1, 0, 0, 0, 1063, 1066, 1, 0, 0, 0, 1064, 1062, 1, 0, 0, 0, 1064, 1065, 1, 0, 0, 0, 1065, 1067, 1, 0, 0, 0, 1066, 1064, 1, 0, 0, 0, 1067, 1068, 5, 20, 0, 0, 1068, 183, 1, 0, 0, 0, 1069, 1073, 5, 48, 0, 0, 1070, 1072, 5, 57, 0, 0, 1071, 1070, 1, 0, 0, 0, 1072, 1075, 1, 0, 0, 0, 1073, 1071, 1, 0, 0, 0, 1073, 1074, 1, 0, 0, 0, 1074, 1076, 1, 0, 0, 0, 1075, 1073, 1, 0, 0, 0, 1076, 1080, 5, 6, 0, 0, 1077, 1079, 5, 57, 0, 0, 1078, 1077, 1, 0, 0, 0, 1079, 1082, 1, 0, 0, 0, 1080, 1078, 1, 0, 0, 0, 1080, 1081, 1, 0, 0, 0, 1081, 1083, 1, 0, 0, 0, 1082, 1080, 1, 0, 0, 0, 1083, 1092, 3, 130, 65, 0, 1084, 1086, 5, 57, 0, 0, 1085, 1084, 1, 0, 0, 0, 1086, 1087, 1, 0, 0, 0, 1087, 1085, 1, 0, 0, 0, 1087, 1088, 1, 0, 0, 0, 1088, 1089, 1, 0, 0, 0, 1089, 1091, 3, 130, 65, 0, 1090, 1085, 1, 0, 0, 0, 1091, 1094, 1, 0, 0, 0, 1092, 1090, 1, 0, 0, 0, 1092, 1093, 1, 0, 0, 0, 1093, 1101, 1, 0, 0, 0, 1094, 1092, 1, 0, 0, 0, 1095, 1097, 5, 57, 0, 0, 1096, 1095, 1, 0, 0, 0, 1097, 1098, 1, 0, 0, 0, 1098, 1096, 1, 0, 0, 0, 1098, 1099, 1, 0, 0, 0, 1099, 1100, 1, 0, 0, 0, 1100, 1102, 3, 186, 93, 0, 1101, 1096, 1, 0, 0, 0, 1101, 1102, 1, 0, 0, 0, 1102, 1106, 1, 0, 0, 0, 1103, 1105, 5, 57, 0, 0, 1104, 1103, 1, 0, 0, 0, 1105, 1108, 1, 0, 0, 0, 1106, 1104, 1, 0, 0, 0, 1106, 1107, 1, 0, 0, 0, 1107, 1109, 1, 0, 0, 0, 1108, 1106, 1, 0, 0, 0, 1109, 1110, 5, 7, 0, 0, 1110, 185, 1, 0, 0, 0, 1111, 1112, 5, 49, 0, 0, 1112, 1113, 5, 29, 0, 0, 1113, 1114, 3, 150, 75, 0, 1114, 187, 1, 0, 0, 0, 144, 191, 193, 203, 210, 215, 223, 231, 237, 244, 250, 256, 260, 265, 273, 279, 287, 297, 302, 315, 322, 325, 328, 334, 338, 347, 353, 358, 363, 369, 373, 379, 387, 393, 399, 406, 412, 419, 427, 433, 439, 448, 455, 459, 467, 472, 480, 487, 494, 500, 504, 507, 514, 521, 532, 536, 543, 546, 552, 557, 562, 567, 573, 580, 585, 589, 599, 604, 609, 613, 620, 624, 628, 633, 645, 649, 659, 666, 671, 674, 678, 684, 688, 697, 703, 712, 716, 719, 726, 731, 738, 745, 750, 757, 760, 766, 771, 778, 781, 787, 792, 801, 807, 810, 815, 820, 823, 826, 834, 838, 843, 847, 850, 858, 866, 871, 876, 880, 885, 893, 899, 907, 914, 919, 936, 961, 969, 976, 989, 997, 1005, 1011, 1031, 1038, 1044, 1052, 1059, 1064, 1073, 1080, 1087, 1092, 1098, 1101, 1106] \ No newline at end of file +[4, 1, 58, 1116, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, 2, 92, 7, 92, 2, 93, 7, 93, 1, 0, 1, 0, 1, 0, 5, 0, 192, 8, 0, 10, 0, 12, 0, 195, 9, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 204, 8, 1, 1, 2, 1, 2, 1, 2, 4, 2, 209, 8, 2, 11, 2, 12, 2, 210, 1, 3, 1, 3, 1, 3, 3, 3, 216, 8, 3, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 222, 8, 4, 10, 4, 12, 4, 225, 9, 4, 1, 4, 1, 4, 1, 5, 4, 5, 230, 8, 5, 11, 5, 12, 5, 231, 1, 6, 1, 6, 5, 6, 236, 8, 6, 10, 6, 12, 6, 239, 9, 6, 1, 6, 1, 6, 5, 6, 243, 8, 6, 10, 6, 12, 6, 246, 9, 6, 1, 6, 5, 6, 249, 8, 6, 10, 6, 12, 6, 252, 9, 6, 1, 6, 1, 6, 1, 7, 3, 7, 257, 8, 7, 1, 7, 1, 7, 3, 7, 261, 8, 7, 1, 7, 5, 7, 264, 8, 7, 10, 7, 12, 7, 267, 9, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 3, 9, 274, 8, 9, 1, 9, 1, 9, 1, 10, 1, 10, 3, 10, 280, 8, 10, 1, 11, 1, 11, 1, 11, 1, 11, 5, 11, 286, 8, 11, 10, 11, 12, 11, 289, 9, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 5, 13, 296, 8, 13, 10, 13, 12, 13, 299, 9, 13, 1, 14, 1, 14, 3, 14, 303, 8, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 3, 19, 316, 8, 19, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 3, 20, 323, 8, 20, 1, 20, 3, 20, 326, 8, 20, 1, 20, 3, 20, 329, 8, 20, 1, 21, 1, 21, 5, 21, 333, 8, 21, 10, 21, 12, 21, 336, 9, 21, 1, 21, 3, 21, 339, 8, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 5, 22, 346, 8, 22, 10, 22, 12, 22, 349, 9, 22, 1, 22, 5, 22, 352, 8, 22, 10, 22, 12, 22, 355, 9, 22, 1, 23, 1, 23, 3, 23, 359, 8, 23, 1, 23, 5, 23, 362, 8, 23, 10, 23, 12, 23, 365, 9, 23, 1, 24, 1, 24, 1, 24, 3, 24, 370, 8, 24, 1, 25, 1, 25, 3, 25, 374, 8, 25, 1, 26, 1, 26, 5, 26, 378, 8, 26, 10, 26, 12, 26, 381, 9, 26, 1, 26, 1, 26, 1, 26, 5, 26, 386, 8, 26, 10, 26, 12, 26, 389, 9, 26, 1, 26, 5, 26, 392, 8, 26, 10, 26, 12, 26, 395, 9, 26, 1, 26, 5, 26, 398, 8, 26, 10, 26, 12, 26, 401, 9, 26, 1, 26, 1, 26, 1, 27, 1, 27, 3, 27, 407, 8, 27, 1, 28, 1, 28, 5, 28, 411, 8, 28, 10, 28, 12, 28, 414, 9, 28, 1, 28, 1, 28, 5, 28, 418, 8, 28, 10, 28, 12, 28, 421, 9, 28, 1, 28, 1, 28, 1, 28, 5, 28, 426, 8, 28, 10, 28, 12, 28, 429, 9, 28, 1, 28, 5, 28, 432, 8, 28, 10, 28, 12, 28, 435, 9, 28, 1, 28, 5, 28, 438, 8, 28, 10, 28, 12, 28, 441, 9, 28, 1, 28, 1, 28, 1, 29, 1, 29, 5, 29, 447, 8, 29, 10, 29, 12, 29, 450, 9, 29, 1, 29, 1, 29, 5, 29, 454, 8, 29, 10, 29, 12, 29, 457, 9, 29, 1, 29, 3, 29, 460, 8, 29, 1, 29, 1, 29, 1, 30, 1, 30, 4, 30, 466, 8, 30, 11, 30, 12, 30, 467, 1, 30, 5, 30, 471, 8, 30, 10, 30, 12, 30, 474, 9, 30, 1, 31, 1, 31, 1, 31, 5, 31, 479, 8, 31, 10, 31, 12, 31, 482, 9, 31, 1, 32, 1, 32, 5, 32, 486, 8, 32, 10, 32, 12, 32, 489, 9, 32, 1, 32, 1, 32, 5, 32, 493, 8, 32, 10, 32, 12, 32, 496, 9, 32, 1, 32, 4, 32, 499, 8, 32, 11, 32, 12, 32, 500, 1, 33, 1, 33, 3, 33, 505, 8, 33, 1, 34, 3, 34, 508, 8, 34, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 3, 35, 515, 8, 35, 1, 35, 1, 35, 1, 35, 5, 35, 520, 8, 35, 10, 35, 12, 35, 523, 9, 35, 1, 36, 1, 36, 1, 37, 1, 37, 1, 38, 1, 38, 5, 38, 531, 8, 38, 10, 38, 12, 38, 534, 9, 38, 1, 38, 3, 38, 537, 8, 38, 1, 38, 1, 38, 1, 38, 5, 38, 542, 8, 38, 10, 38, 12, 38, 545, 9, 38, 3, 38, 547, 8, 38, 1, 38, 1, 38, 1, 39, 1, 39, 3, 39, 553, 8, 39, 1, 40, 5, 40, 556, 8, 40, 10, 40, 12, 40, 559, 9, 40, 1, 40, 3, 40, 562, 8, 40, 1, 40, 1, 40, 5, 40, 566, 8, 40, 10, 40, 12, 40, 569, 9, 40, 1, 41, 5, 41, 572, 8, 41, 10, 41, 12, 41, 575, 9, 41, 1, 41, 1, 41, 1, 41, 1, 41, 3, 41, 581, 8, 41, 1, 41, 5, 41, 584, 8, 41, 10, 41, 12, 41, 587, 9, 41, 1, 42, 3, 42, 590, 8, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 3, 43, 600, 8, 43, 1, 43, 5, 43, 603, 8, 43, 10, 43, 12, 43, 606, 9, 43, 1, 44, 1, 44, 3, 44, 610, 8, 44, 1, 44, 1, 44, 3, 44, 614, 8, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 3, 44, 621, 8, 44, 1, 45, 1, 45, 3, 45, 625, 8, 45, 1, 45, 1, 45, 3, 45, 629, 8, 45, 1, 45, 1, 45, 1, 45, 3, 45, 634, 8, 45, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 5, 48, 644, 8, 48, 10, 48, 12, 48, 647, 9, 48, 1, 48, 3, 48, 650, 8, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 5, 49, 658, 8, 49, 10, 49, 12, 49, 661, 9, 49, 1, 49, 1, 49, 5, 49, 665, 8, 49, 10, 49, 12, 49, 668, 9, 49, 5, 49, 670, 8, 49, 10, 49, 12, 49, 673, 9, 49, 3, 49, 675, 8, 49, 1, 50, 1, 50, 3, 50, 679, 8, 50, 1, 51, 1, 51, 5, 51, 683, 8, 51, 10, 51, 12, 51, 686, 9, 51, 1, 51, 3, 51, 689, 8, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 5, 52, 696, 8, 52, 10, 52, 12, 52, 699, 9, 52, 1, 52, 5, 52, 702, 8, 52, 10, 52, 12, 52, 705, 9, 52, 1, 53, 1, 53, 1, 53, 1, 53, 5, 53, 711, 8, 53, 10, 53, 12, 53, 714, 9, 53, 1, 54, 3, 54, 717, 8, 54, 1, 54, 3, 54, 720, 8, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 3, 55, 727, 8, 55, 1, 55, 5, 55, 730, 8, 55, 10, 55, 12, 55, 733, 9, 55, 1, 56, 1, 56, 5, 56, 737, 8, 56, 10, 56, 12, 56, 740, 9, 56, 1, 56, 1, 56, 5, 56, 744, 8, 56, 10, 56, 12, 56, 747, 9, 56, 5, 56, 749, 8, 56, 10, 56, 12, 56, 752, 9, 56, 1, 56, 1, 56, 5, 56, 756, 8, 56, 10, 56, 12, 56, 759, 9, 56, 3, 56, 761, 8, 56, 1, 56, 1, 56, 5, 56, 765, 8, 56, 10, 56, 12, 56, 768, 9, 56, 5, 56, 770, 8, 56, 10, 56, 12, 56, 773, 9, 56, 1, 56, 1, 56, 5, 56, 777, 8, 56, 10, 56, 12, 56, 780, 9, 56, 3, 56, 782, 8, 56, 1, 56, 1, 56, 5, 56, 786, 8, 56, 10, 56, 12, 56, 789, 9, 56, 5, 56, 791, 8, 56, 10, 56, 12, 56, 794, 9, 56, 1, 56, 1, 56, 1, 57, 1, 57, 4, 57, 800, 8, 57, 11, 57, 12, 57, 801, 1, 57, 1, 57, 1, 58, 1, 58, 3, 58, 808, 8, 58, 1, 58, 3, 58, 811, 8, 58, 1, 58, 5, 58, 814, 8, 58, 10, 58, 12, 58, 817, 9, 58, 4, 58, 819, 8, 58, 11, 58, 12, 58, 820, 1, 59, 3, 59, 824, 8, 59, 1, 59, 3, 59, 827, 8, 59, 1, 59, 1, 59, 1, 60, 1, 60, 5, 60, 833, 8, 60, 10, 60, 12, 60, 836, 9, 60, 1, 60, 3, 60, 839, 8, 60, 1, 60, 5, 60, 842, 8, 60, 10, 60, 12, 60, 845, 9, 60, 1, 60, 3, 60, 848, 8, 60, 1, 60, 3, 60, 851, 8, 60, 1, 61, 1, 61, 1, 62, 1, 62, 5, 62, 857, 8, 62, 10, 62, 12, 62, 860, 9, 62, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 3, 63, 867, 8, 63, 1, 63, 5, 63, 870, 8, 63, 10, 63, 12, 63, 873, 9, 63, 1, 63, 1, 63, 3, 63, 877, 8, 63, 5, 63, 879, 8, 63, 10, 63, 12, 63, 882, 9, 63, 1, 64, 1, 64, 3, 64, 886, 8, 64, 1, 65, 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 3, 66, 894, 8, 66, 1, 67, 1, 67, 5, 67, 898, 8, 67, 10, 67, 12, 67, 901, 9, 67, 1, 67, 1, 67, 1, 67, 5, 67, 906, 8, 67, 10, 67, 12, 67, 909, 9, 67, 1, 67, 1, 67, 5, 67, 913, 8, 67, 10, 67, 12, 67, 916, 9, 67, 5, 67, 918, 8, 67, 10, 67, 12, 67, 921, 9, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 3, 69, 937, 8, 69, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 74, 1, 74, 1, 75, 1, 75, 3, 75, 962, 8, 75, 1, 76, 1, 76, 1, 77, 1, 77, 5, 77, 968, 8, 77, 10, 77, 12, 77, 971, 9, 77, 1, 77, 1, 77, 5, 77, 975, 8, 77, 10, 77, 12, 77, 978, 9, 77, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 1, 79, 1, 79, 1, 79, 1, 79, 1, 80, 3, 80, 990, 8, 80, 1, 80, 1, 80, 1, 81, 1, 81, 1, 81, 1, 81, 3, 81, 998, 8, 81, 1, 82, 1, 82, 1, 83, 1, 83, 1, 83, 1, 84, 3, 84, 1006, 8, 84, 1, 84, 1, 84, 1, 84, 1, 85, 3, 85, 1012, 8, 85, 1, 85, 1, 85, 1, 85, 1, 85, 1, 86, 1, 86, 1, 87, 1, 87, 1, 88, 1, 88, 1, 88, 1, 88, 1, 89, 1, 89, 1, 89, 1, 89, 5, 89, 1030, 8, 89, 10, 89, 12, 89, 1033, 9, 89, 1, 90, 1, 90, 1, 90, 1, 90, 3, 90, 1039, 8, 90, 1, 91, 1, 91, 5, 91, 1043, 8, 91, 10, 91, 12, 91, 1046, 9, 91, 1, 91, 1, 91, 1, 91, 5, 91, 1051, 8, 91, 10, 91, 12, 91, 1054, 9, 91, 1, 91, 1, 91, 5, 91, 1058, 8, 91, 10, 91, 12, 91, 1061, 9, 91, 5, 91, 1063, 8, 91, 10, 91, 12, 91, 1066, 9, 91, 1, 91, 1, 91, 1, 92, 1, 92, 5, 92, 1072, 8, 92, 10, 92, 12, 92, 1075, 9, 92, 1, 92, 1, 92, 5, 92, 1079, 8, 92, 10, 92, 12, 92, 1082, 9, 92, 1, 92, 1, 92, 4, 92, 1086, 8, 92, 11, 92, 12, 92, 1087, 1, 92, 5, 92, 1091, 8, 92, 10, 92, 12, 92, 1094, 9, 92, 1, 92, 4, 92, 1097, 8, 92, 11, 92, 12, 92, 1098, 1, 92, 3, 92, 1102, 8, 92, 1, 92, 5, 92, 1105, 8, 92, 10, 92, 12, 92, 1108, 9, 92, 1, 92, 1, 92, 1, 93, 1, 93, 1, 93, 1, 93, 1, 93, 0, 0, 94, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 0, 4, 1, 0, 10, 11, 1, 0, 23, 24, 2, 0, 31, 33, 54, 54, 5, 0, 10, 10, 13, 14, 17, 17, 34, 45, 54, 54, 1189, 0, 193, 1, 0, 0, 0, 2, 203, 1, 0, 0, 0, 4, 208, 1, 0, 0, 0, 6, 212, 1, 0, 0, 0, 8, 217, 1, 0, 0, 0, 10, 229, 1, 0, 0, 0, 12, 233, 1, 0, 0, 0, 14, 256, 1, 0, 0, 0, 16, 268, 1, 0, 0, 0, 18, 273, 1, 0, 0, 0, 20, 279, 1, 0, 0, 0, 22, 281, 1, 0, 0, 0, 24, 290, 1, 0, 0, 0, 26, 292, 1, 0, 0, 0, 28, 302, 1, 0, 0, 0, 30, 304, 1, 0, 0, 0, 32, 306, 1, 0, 0, 0, 34, 310, 1, 0, 0, 0, 36, 312, 1, 0, 0, 0, 38, 315, 1, 0, 0, 0, 40, 320, 1, 0, 0, 0, 42, 330, 1, 0, 0, 0, 44, 342, 1, 0, 0, 0, 46, 356, 1, 0, 0, 0, 48, 369, 1, 0, 0, 0, 50, 371, 1, 0, 0, 0, 52, 375, 1, 0, 0, 0, 54, 406, 1, 0, 0, 0, 56, 408, 1, 0, 0, 0, 58, 444, 1, 0, 0, 0, 60, 463, 1, 0, 0, 0, 62, 475, 1, 0, 0, 0, 64, 483, 1, 0, 0, 0, 66, 504, 1, 0, 0, 0, 68, 507, 1, 0, 0, 0, 70, 512, 1, 0, 0, 0, 72, 524, 1, 0, 0, 0, 74, 526, 1, 0, 0, 0, 76, 528, 1, 0, 0, 0, 78, 552, 1, 0, 0, 0, 80, 557, 1, 0, 0, 0, 82, 573, 1, 0, 0, 0, 84, 589, 1, 0, 0, 0, 86, 594, 1, 0, 0, 0, 88, 620, 1, 0, 0, 0, 90, 633, 1, 0, 0, 0, 92, 635, 1, 0, 0, 0, 94, 637, 1, 0, 0, 0, 96, 641, 1, 0, 0, 0, 98, 674, 1, 0, 0, 0, 100, 678, 1, 0, 0, 0, 102, 680, 1, 0, 0, 0, 104, 692, 1, 0, 0, 0, 106, 706, 1, 0, 0, 0, 108, 716, 1, 0, 0, 0, 110, 724, 1, 0, 0, 0, 112, 734, 1, 0, 0, 0, 114, 797, 1, 0, 0, 0, 116, 818, 1, 0, 0, 0, 118, 823, 1, 0, 0, 0, 120, 830, 1, 0, 0, 0, 122, 852, 1, 0, 0, 0, 124, 854, 1, 0, 0, 0, 126, 866, 1, 0, 0, 0, 128, 885, 1, 0, 0, 0, 130, 887, 1, 0, 0, 0, 132, 893, 1, 0, 0, 0, 134, 895, 1, 0, 0, 0, 136, 924, 1, 0, 0, 0, 138, 936, 1, 0, 0, 0, 140, 938, 1, 0, 0, 0, 142, 941, 1, 0, 0, 0, 144, 943, 1, 0, 0, 0, 146, 951, 1, 0, 0, 0, 148, 957, 1, 0, 0, 0, 150, 961, 1, 0, 0, 0, 152, 963, 1, 0, 0, 0, 154, 965, 1, 0, 0, 0, 156, 981, 1, 0, 0, 0, 158, 984, 1, 0, 0, 0, 160, 989, 1, 0, 0, 0, 162, 997, 1, 0, 0, 0, 164, 999, 1, 0, 0, 0, 166, 1001, 1, 0, 0, 0, 168, 1005, 1, 0, 0, 0, 170, 1011, 1, 0, 0, 0, 172, 1017, 1, 0, 0, 0, 174, 1019, 1, 0, 0, 0, 176, 1021, 1, 0, 0, 0, 178, 1025, 1, 0, 0, 0, 180, 1038, 1, 0, 0, 0, 182, 1040, 1, 0, 0, 0, 184, 1069, 1, 0, 0, 0, 186, 1111, 1, 0, 0, 0, 188, 192, 5, 57, 0, 0, 189, 192, 5, 50, 0, 0, 190, 192, 3, 2, 1, 0, 191, 188, 1, 0, 0, 0, 191, 189, 1, 0, 0, 0, 191, 190, 1, 0, 0, 0, 192, 195, 1, 0, 0, 0, 193, 191, 1, 0, 0, 0, 193, 194, 1, 0, 0, 0, 194, 196, 1, 0, 0, 0, 195, 193, 1, 0, 0, 0, 196, 197, 5, 0, 0, 1, 197, 1, 1, 0, 0, 0, 198, 204, 3, 12, 6, 0, 199, 204, 3, 38, 19, 0, 200, 204, 3, 68, 34, 0, 201, 204, 3, 84, 42, 0, 202, 204, 3, 108, 54, 0, 203, 198, 1, 0, 0, 0, 203, 199, 1, 0, 0, 0, 203, 200, 1, 0, 0, 0, 203, 201, 1, 0, 0, 0, 203, 202, 1, 0, 0, 0, 204, 3, 1, 0, 0, 0, 205, 206, 3, 6, 3, 0, 206, 207, 5, 57, 0, 0, 207, 209, 1, 0, 0, 0, 208, 205, 1, 0, 0, 0, 209, 210, 1, 0, 0, 0, 210, 208, 1, 0, 0, 0, 210, 211, 1, 0, 0, 0, 211, 5, 1, 0, 0, 0, 212, 213, 5, 1, 0, 0, 213, 215, 5, 52, 0, 0, 214, 216, 3, 8, 4, 0, 215, 214, 1, 0, 0, 0, 215, 216, 1, 0, 0, 0, 216, 7, 1, 0, 0, 0, 217, 218, 5, 2, 0, 0, 218, 223, 3, 10, 5, 0, 219, 220, 5, 3, 0, 0, 220, 222, 3, 10, 5, 0, 221, 219, 1, 0, 0, 0, 222, 225, 1, 0, 0, 0, 223, 221, 1, 0, 0, 0, 223, 224, 1, 0, 0, 0, 224, 226, 1, 0, 0, 0, 225, 223, 1, 0, 0, 0, 226, 227, 5, 4, 0, 0, 227, 9, 1, 0, 0, 0, 228, 230, 5, 52, 0, 0, 229, 228, 1, 0, 0, 0, 230, 231, 1, 0, 0, 0, 231, 229, 1, 0, 0, 0, 231, 232, 1, 0, 0, 0, 232, 11, 1, 0, 0, 0, 233, 237, 5, 5, 0, 0, 234, 236, 5, 57, 0, 0, 235, 234, 1, 0, 0, 0, 236, 239, 1, 0, 0, 0, 237, 235, 1, 0, 0, 0, 237, 238, 1, 0, 0, 0, 238, 240, 1, 0, 0, 0, 239, 237, 1, 0, 0, 0, 240, 244, 5, 6, 0, 0, 241, 243, 5, 57, 0, 0, 242, 241, 1, 0, 0, 0, 243, 246, 1, 0, 0, 0, 244, 242, 1, 0, 0, 0, 244, 245, 1, 0, 0, 0, 245, 250, 1, 0, 0, 0, 246, 244, 1, 0, 0, 0, 247, 249, 3, 14, 7, 0, 248, 247, 1, 0, 0, 0, 249, 252, 1, 0, 0, 0, 250, 248, 1, 0, 0, 0, 250, 251, 1, 0, 0, 0, 251, 253, 1, 0, 0, 0, 252, 250, 1, 0, 0, 0, 253, 254, 5, 7, 0, 0, 254, 13, 1, 0, 0, 0, 255, 257, 3, 16, 8, 0, 256, 255, 1, 0, 0, 0, 256, 257, 1, 0, 0, 0, 257, 258, 1, 0, 0, 0, 258, 260, 3, 18, 9, 0, 259, 261, 5, 3, 0, 0, 260, 259, 1, 0, 0, 0, 260, 261, 1, 0, 0, 0, 261, 265, 1, 0, 0, 0, 262, 264, 5, 57, 0, 0, 263, 262, 1, 0, 0, 0, 264, 267, 1, 0, 0, 0, 265, 263, 1, 0, 0, 0, 265, 266, 1, 0, 0, 0, 266, 15, 1, 0, 0, 0, 267, 265, 1, 0, 0, 0, 268, 269, 5, 52, 0, 0, 269, 17, 1, 0, 0, 0, 270, 271, 3, 20, 10, 0, 271, 272, 5, 8, 0, 0, 272, 274, 1, 0, 0, 0, 273, 270, 1, 0, 0, 0, 273, 274, 1, 0, 0, 0, 274, 275, 1, 0, 0, 0, 275, 276, 3, 26, 13, 0, 276, 19, 1, 0, 0, 0, 277, 280, 5, 9, 0, 0, 278, 280, 3, 22, 11, 0, 279, 277, 1, 0, 0, 0, 279, 278, 1, 0, 0, 0, 280, 21, 1, 0, 0, 0, 281, 287, 5, 52, 0, 0, 282, 283, 3, 24, 12, 0, 283, 284, 5, 52, 0, 0, 284, 286, 1, 0, 0, 0, 285, 282, 1, 0, 0, 0, 286, 289, 1, 0, 0, 0, 287, 285, 1, 0, 0, 0, 287, 288, 1, 0, 0, 0, 288, 23, 1, 0, 0, 0, 289, 287, 1, 0, 0, 0, 290, 291, 7, 0, 0, 0, 291, 25, 1, 0, 0, 0, 292, 297, 5, 52, 0, 0, 293, 294, 5, 10, 0, 0, 294, 296, 5, 52, 0, 0, 295, 293, 1, 0, 0, 0, 296, 299, 1, 0, 0, 0, 297, 295, 1, 0, 0, 0, 297, 298, 1, 0, 0, 0, 298, 27, 1, 0, 0, 0, 299, 297, 1, 0, 0, 0, 300, 303, 3, 32, 16, 0, 301, 303, 3, 30, 15, 0, 302, 300, 1, 0, 0, 0, 302, 301, 1, 0, 0, 0, 303, 29, 1, 0, 0, 0, 304, 305, 5, 52, 0, 0, 305, 31, 1, 0, 0, 0, 306, 307, 3, 34, 17, 0, 307, 308, 5, 11, 0, 0, 308, 309, 3, 36, 18, 0, 309, 33, 1, 0, 0, 0, 310, 311, 5, 52, 0, 0, 311, 35, 1, 0, 0, 0, 312, 313, 5, 52, 0, 0, 313, 37, 1, 0, 0, 0, 314, 316, 5, 51, 0, 0, 315, 314, 1, 0, 0, 0, 315, 316, 1, 0, 0, 0, 316, 317, 1, 0, 0, 0, 317, 318, 5, 12, 0, 0, 318, 319, 3, 40, 20, 0, 319, 39, 1, 0, 0, 0, 320, 322, 5, 52, 0, 0, 321, 323, 3, 42, 21, 0, 322, 321, 1, 0, 0, 0, 322, 323, 1, 0, 0, 0, 323, 325, 1, 0, 0, 0, 324, 326, 3, 48, 24, 0, 325, 324, 1, 0, 0, 0, 325, 326, 1, 0, 0, 0, 326, 328, 1, 0, 0, 0, 327, 329, 5, 50, 0, 0, 328, 327, 1, 0, 0, 0, 328, 329, 1, 0, 0, 0, 329, 41, 1, 0, 0, 0, 330, 334, 5, 13, 0, 0, 331, 333, 5, 57, 0, 0, 332, 331, 1, 0, 0, 0, 333, 336, 1, 0, 0, 0, 334, 332, 1, 0, 0, 0, 334, 335, 1, 0, 0, 0, 335, 338, 1, 0, 0, 0, 336, 334, 1, 0, 0, 0, 337, 339, 3, 44, 22, 0, 338, 337, 1, 0, 0, 0, 338, 339, 1, 0, 0, 0, 339, 340, 1, 0, 0, 0, 340, 341, 5, 14, 0, 0, 341, 43, 1, 0, 0, 0, 342, 353, 3, 46, 23, 0, 343, 347, 5, 3, 0, 0, 344, 346, 5, 57, 0, 0, 345, 344, 1, 0, 0, 0, 346, 349, 1, 0, 0, 0, 347, 345, 1, 0, 0, 0, 347, 348, 1, 0, 0, 0, 348, 350, 1, 0, 0, 0, 349, 347, 1, 0, 0, 0, 350, 352, 3, 46, 23, 0, 351, 343, 1, 0, 0, 0, 352, 355, 1, 0, 0, 0, 353, 351, 1, 0, 0, 0, 353, 354, 1, 0, 0, 0, 354, 45, 1, 0, 0, 0, 355, 353, 1, 0, 0, 0, 356, 358, 5, 52, 0, 0, 357, 359, 3, 48, 24, 0, 358, 357, 1, 0, 0, 0, 358, 359, 1, 0, 0, 0, 359, 363, 1, 0, 0, 0, 360, 362, 5, 57, 0, 0, 361, 360, 1, 0, 0, 0, 362, 365, 1, 0, 0, 0, 363, 361, 1, 0, 0, 0, 363, 364, 1, 0, 0, 0, 364, 47, 1, 0, 0, 0, 365, 363, 1, 0, 0, 0, 366, 370, 3, 50, 25, 0, 367, 370, 3, 54, 27, 0, 368, 370, 3, 64, 32, 0, 369, 366, 1, 0, 0, 0, 369, 367, 1, 0, 0, 0, 369, 368, 1, 0, 0, 0, 370, 49, 1, 0, 0, 0, 371, 373, 3, 28, 14, 0, 372, 374, 3, 52, 26, 0, 373, 372, 1, 0, 0, 0, 373, 374, 1, 0, 0, 0, 374, 51, 1, 0, 0, 0, 375, 379, 5, 13, 0, 0, 376, 378, 5, 57, 0, 0, 377, 376, 1, 0, 0, 0, 378, 381, 1, 0, 0, 0, 379, 377, 1, 0, 0, 0, 379, 380, 1, 0, 0, 0, 380, 382, 1, 0, 0, 0, 381, 379, 1, 0, 0, 0, 382, 393, 3, 48, 24, 0, 383, 387, 5, 3, 0, 0, 384, 386, 5, 57, 0, 0, 385, 384, 1, 0, 0, 0, 386, 389, 1, 0, 0, 0, 387, 385, 1, 0, 0, 0, 387, 388, 1, 0, 0, 0, 388, 390, 1, 0, 0, 0, 389, 387, 1, 0, 0, 0, 390, 392, 3, 48, 24, 0, 391, 383, 1, 0, 0, 0, 392, 395, 1, 0, 0, 0, 393, 391, 1, 0, 0, 0, 393, 394, 1, 0, 0, 0, 394, 399, 1, 0, 0, 0, 395, 393, 1, 0, 0, 0, 396, 398, 5, 57, 0, 0, 397, 396, 1, 0, 0, 0, 398, 401, 1, 0, 0, 0, 399, 397, 1, 0, 0, 0, 399, 400, 1, 0, 0, 0, 400, 402, 1, 0, 0, 0, 401, 399, 1, 0, 0, 0, 402, 403, 5, 14, 0, 0, 403, 53, 1, 0, 0, 0, 404, 407, 3, 56, 28, 0, 405, 407, 3, 58, 29, 0, 406, 404, 1, 0, 0, 0, 406, 405, 1, 0, 0, 0, 407, 55, 1, 0, 0, 0, 408, 412, 5, 15, 0, 0, 409, 411, 5, 57, 0, 0, 410, 409, 1, 0, 0, 0, 411, 414, 1, 0, 0, 0, 412, 410, 1, 0, 0, 0, 412, 413, 1, 0, 0, 0, 413, 415, 1, 0, 0, 0, 414, 412, 1, 0, 0, 0, 415, 419, 5, 6, 0, 0, 416, 418, 5, 57, 0, 0, 417, 416, 1, 0, 0, 0, 418, 421, 1, 0, 0, 0, 419, 417, 1, 0, 0, 0, 419, 420, 1, 0, 0, 0, 420, 422, 1, 0, 0, 0, 421, 419, 1, 0, 0, 0, 422, 433, 5, 52, 0, 0, 423, 427, 5, 3, 0, 0, 424, 426, 5, 57, 0, 0, 425, 424, 1, 0, 0, 0, 426, 429, 1, 0, 0, 0, 427, 425, 1, 0, 0, 0, 427, 428, 1, 0, 0, 0, 428, 430, 1, 0, 0, 0, 429, 427, 1, 0, 0, 0, 430, 432, 5, 52, 0, 0, 431, 423, 1, 0, 0, 0, 432, 435, 1, 0, 0, 0, 433, 431, 1, 0, 0, 0, 433, 434, 1, 0, 0, 0, 434, 439, 1, 0, 0, 0, 435, 433, 1, 0, 0, 0, 436, 438, 5, 57, 0, 0, 437, 436, 1, 0, 0, 0, 438, 441, 1, 0, 0, 0, 439, 437, 1, 0, 0, 0, 439, 440, 1, 0, 0, 0, 440, 442, 1, 0, 0, 0, 441, 439, 1, 0, 0, 0, 442, 443, 5, 7, 0, 0, 443, 57, 1, 0, 0, 0, 444, 448, 5, 16, 0, 0, 445, 447, 5, 57, 0, 0, 446, 445, 1, 0, 0, 0, 447, 450, 1, 0, 0, 0, 448, 446, 1, 0, 0, 0, 448, 449, 1, 0, 0, 0, 449, 451, 1, 0, 0, 0, 450, 448, 1, 0, 0, 0, 451, 455, 5, 6, 0, 0, 452, 454, 5, 57, 0, 0, 453, 452, 1, 0, 0, 0, 454, 457, 1, 0, 0, 0, 455, 453, 1, 0, 0, 0, 455, 456, 1, 0, 0, 0, 456, 459, 1, 0, 0, 0, 457, 455, 1, 0, 0, 0, 458, 460, 3, 60, 30, 0, 459, 458, 1, 0, 0, 0, 459, 460, 1, 0, 0, 0, 460, 461, 1, 0, 0, 0, 461, 462, 5, 7, 0, 0, 462, 59, 1, 0, 0, 0, 463, 472, 3, 62, 31, 0, 464, 466, 5, 57, 0, 0, 465, 464, 1, 0, 0, 0, 466, 467, 1, 0, 0, 0, 467, 465, 1, 0, 0, 0, 467, 468, 1, 0, 0, 0, 468, 469, 1, 0, 0, 0, 469, 471, 3, 62, 31, 0, 470, 465, 1, 0, 0, 0, 471, 474, 1, 0, 0, 0, 472, 470, 1, 0, 0, 0, 472, 473, 1, 0, 0, 0, 473, 61, 1, 0, 0, 0, 474, 472, 1, 0, 0, 0, 475, 476, 5, 52, 0, 0, 476, 480, 3, 48, 24, 0, 477, 479, 5, 57, 0, 0, 478, 477, 1, 0, 0, 0, 479, 482, 1, 0, 0, 0, 480, 478, 1, 0, 0, 0, 480, 481, 1, 0, 0, 0, 481, 63, 1, 0, 0, 0, 482, 480, 1, 0, 0, 0, 483, 498, 3, 66, 33, 0, 484, 486, 5, 57, 0, 0, 485, 484, 1, 0, 0, 0, 486, 489, 1, 0, 0, 0, 487, 485, 1, 0, 0, 0, 487, 488, 1, 0, 0, 0, 488, 490, 1, 0, 0, 0, 489, 487, 1, 0, 0, 0, 490, 494, 5, 17, 0, 0, 491, 493, 5, 57, 0, 0, 492, 491, 1, 0, 0, 0, 493, 496, 1, 0, 0, 0, 494, 492, 1, 0, 0, 0, 494, 495, 1, 0, 0, 0, 495, 497, 1, 0, 0, 0, 496, 494, 1, 0, 0, 0, 497, 499, 3, 66, 33, 0, 498, 487, 1, 0, 0, 0, 499, 500, 1, 0, 0, 0, 500, 498, 1, 0, 0, 0, 500, 501, 1, 0, 0, 0, 501, 65, 1, 0, 0, 0, 502, 505, 3, 50, 25, 0, 503, 505, 3, 54, 27, 0, 504, 502, 1, 0, 0, 0, 504, 503, 1, 0, 0, 0, 505, 67, 1, 0, 0, 0, 506, 508, 5, 51, 0, 0, 507, 506, 1, 0, 0, 0, 507, 508, 1, 0, 0, 0, 508, 509, 1, 0, 0, 0, 509, 510, 5, 18, 0, 0, 510, 511, 3, 70, 35, 0, 511, 69, 1, 0, 0, 0, 512, 514, 5, 52, 0, 0, 513, 515, 3, 42, 21, 0, 514, 513, 1, 0, 0, 0, 514, 515, 1, 0, 0, 0, 515, 516, 1, 0, 0, 0, 516, 517, 3, 72, 36, 0, 517, 521, 3, 74, 37, 0, 518, 520, 5, 57, 0, 0, 519, 518, 1, 0, 0, 0, 520, 523, 1, 0, 0, 0, 521, 519, 1, 0, 0, 0, 521, 522, 1, 0, 0, 0, 522, 71, 1, 0, 0, 0, 523, 521, 1, 0, 0, 0, 524, 525, 3, 76, 38, 0, 525, 73, 1, 0, 0, 0, 526, 527, 3, 76, 38, 0, 527, 75, 1, 0, 0, 0, 528, 546, 5, 2, 0, 0, 529, 531, 5, 57, 0, 0, 530, 529, 1, 0, 0, 0, 531, 534, 1, 0, 0, 0, 532, 530, 1, 0, 0, 0, 532, 533, 1, 0, 0, 0, 533, 547, 1, 0, 0, 0, 534, 532, 1, 0, 0, 0, 535, 537, 3, 78, 39, 0, 536, 535, 1, 0, 0, 0, 536, 537, 1, 0, 0, 0, 537, 547, 1, 0, 0, 0, 538, 543, 3, 78, 39, 0, 539, 540, 5, 3, 0, 0, 540, 542, 3, 78, 39, 0, 541, 539, 1, 0, 0, 0, 542, 545, 1, 0, 0, 0, 543, 541, 1, 0, 0, 0, 543, 544, 1, 0, 0, 0, 544, 547, 1, 0, 0, 0, 545, 543, 1, 0, 0, 0, 546, 532, 1, 0, 0, 0, 546, 536, 1, 0, 0, 0, 546, 538, 1, 0, 0, 0, 547, 548, 1, 0, 0, 0, 548, 549, 5, 4, 0, 0, 549, 77, 1, 0, 0, 0, 550, 553, 3, 80, 40, 0, 551, 553, 3, 82, 41, 0, 552, 550, 1, 0, 0, 0, 552, 551, 1, 0, 0, 0, 553, 79, 1, 0, 0, 0, 554, 556, 5, 57, 0, 0, 555, 554, 1, 0, 0, 0, 556, 559, 1, 0, 0, 0, 557, 555, 1, 0, 0, 0, 557, 558, 1, 0, 0, 0, 558, 561, 1, 0, 0, 0, 559, 557, 1, 0, 0, 0, 560, 562, 5, 52, 0, 0, 561, 560, 1, 0, 0, 0, 561, 562, 1, 0, 0, 0, 562, 563, 1, 0, 0, 0, 563, 567, 3, 48, 24, 0, 564, 566, 5, 57, 0, 0, 565, 564, 1, 0, 0, 0, 566, 569, 1, 0, 0, 0, 567, 565, 1, 0, 0, 0, 567, 568, 1, 0, 0, 0, 568, 81, 1, 0, 0, 0, 569, 567, 1, 0, 0, 0, 570, 572, 5, 57, 0, 0, 571, 570, 1, 0, 0, 0, 572, 575, 1, 0, 0, 0, 573, 571, 1, 0, 0, 0, 573, 574, 1, 0, 0, 0, 574, 576, 1, 0, 0, 0, 575, 573, 1, 0, 0, 0, 576, 577, 5, 19, 0, 0, 577, 578, 5, 52, 0, 0, 578, 580, 5, 20, 0, 0, 579, 581, 3, 48, 24, 0, 580, 579, 1, 0, 0, 0, 580, 581, 1, 0, 0, 0, 581, 585, 1, 0, 0, 0, 582, 584, 5, 57, 0, 0, 583, 582, 1, 0, 0, 0, 584, 587, 1, 0, 0, 0, 585, 583, 1, 0, 0, 0, 585, 586, 1, 0, 0, 0, 586, 83, 1, 0, 0, 0, 587, 585, 1, 0, 0, 0, 588, 590, 5, 51, 0, 0, 589, 588, 1, 0, 0, 0, 589, 590, 1, 0, 0, 0, 590, 591, 1, 0, 0, 0, 591, 592, 5, 21, 0, 0, 592, 593, 3, 86, 43, 0, 593, 85, 1, 0, 0, 0, 594, 595, 5, 52, 0, 0, 595, 596, 3, 48, 24, 0, 596, 599, 5, 22, 0, 0, 597, 600, 3, 28, 14, 0, 598, 600, 3, 88, 44, 0, 599, 597, 1, 0, 0, 0, 599, 598, 1, 0, 0, 0, 600, 604, 1, 0, 0, 0, 601, 603, 5, 57, 0, 0, 602, 601, 1, 0, 0, 0, 603, 606, 1, 0, 0, 0, 604, 602, 1, 0, 0, 0, 604, 605, 1, 0, 0, 0, 605, 87, 1, 0, 0, 0, 606, 604, 1, 0, 0, 0, 607, 621, 3, 92, 46, 0, 608, 610, 5, 54, 0, 0, 609, 608, 1, 0, 0, 0, 609, 610, 1, 0, 0, 0, 610, 611, 1, 0, 0, 0, 611, 621, 5, 53, 0, 0, 612, 614, 5, 54, 0, 0, 613, 612, 1, 0, 0, 0, 613, 614, 1, 0, 0, 0, 614, 615, 1, 0, 0, 0, 615, 621, 5, 55, 0, 0, 616, 621, 5, 56, 0, 0, 617, 621, 3, 94, 47, 0, 618, 621, 3, 96, 48, 0, 619, 621, 3, 102, 51, 0, 620, 607, 1, 0, 0, 0, 620, 609, 1, 0, 0, 0, 620, 613, 1, 0, 0, 0, 620, 616, 1, 0, 0, 0, 620, 617, 1, 0, 0, 0, 620, 618, 1, 0, 0, 0, 620, 619, 1, 0, 0, 0, 621, 89, 1, 0, 0, 0, 622, 634, 3, 92, 46, 0, 623, 625, 5, 54, 0, 0, 624, 623, 1, 0, 0, 0, 624, 625, 1, 0, 0, 0, 625, 626, 1, 0, 0, 0, 626, 634, 5, 53, 0, 0, 627, 629, 5, 54, 0, 0, 628, 627, 1, 0, 0, 0, 628, 629, 1, 0, 0, 0, 629, 630, 1, 0, 0, 0, 630, 634, 5, 55, 0, 0, 631, 634, 5, 56, 0, 0, 632, 634, 3, 94, 47, 0, 633, 622, 1, 0, 0, 0, 633, 624, 1, 0, 0, 0, 633, 628, 1, 0, 0, 0, 633, 631, 1, 0, 0, 0, 633, 632, 1, 0, 0, 0, 634, 91, 1, 0, 0, 0, 635, 636, 7, 1, 0, 0, 636, 93, 1, 0, 0, 0, 637, 638, 3, 28, 14, 0, 638, 639, 5, 25, 0, 0, 639, 640, 5, 52, 0, 0, 640, 95, 1, 0, 0, 0, 641, 645, 5, 19, 0, 0, 642, 644, 5, 57, 0, 0, 643, 642, 1, 0, 0, 0, 644, 647, 1, 0, 0, 0, 645, 643, 1, 0, 0, 0, 645, 646, 1, 0, 0, 0, 646, 649, 1, 0, 0, 0, 647, 645, 1, 0, 0, 0, 648, 650, 3, 98, 49, 0, 649, 648, 1, 0, 0, 0, 649, 650, 1, 0, 0, 0, 650, 651, 1, 0, 0, 0, 651, 652, 5, 20, 0, 0, 652, 97, 1, 0, 0, 0, 653, 675, 3, 100, 50, 0, 654, 671, 3, 100, 50, 0, 655, 659, 5, 3, 0, 0, 656, 658, 5, 57, 0, 0, 657, 656, 1, 0, 0, 0, 658, 661, 1, 0, 0, 0, 659, 657, 1, 0, 0, 0, 659, 660, 1, 0, 0, 0, 660, 662, 1, 0, 0, 0, 661, 659, 1, 0, 0, 0, 662, 666, 3, 100, 50, 0, 663, 665, 5, 57, 0, 0, 664, 663, 1, 0, 0, 0, 665, 668, 1, 0, 0, 0, 666, 664, 1, 0, 0, 0, 666, 667, 1, 0, 0, 0, 667, 670, 1, 0, 0, 0, 668, 666, 1, 0, 0, 0, 669, 655, 1, 0, 0, 0, 670, 673, 1, 0, 0, 0, 671, 669, 1, 0, 0, 0, 671, 672, 1, 0, 0, 0, 672, 675, 1, 0, 0, 0, 673, 671, 1, 0, 0, 0, 674, 653, 1, 0, 0, 0, 674, 654, 1, 0, 0, 0, 675, 99, 1, 0, 0, 0, 676, 679, 3, 28, 14, 0, 677, 679, 3, 88, 44, 0, 678, 676, 1, 0, 0, 0, 678, 677, 1, 0, 0, 0, 679, 101, 1, 0, 0, 0, 680, 684, 5, 6, 0, 0, 681, 683, 5, 57, 0, 0, 682, 681, 1, 0, 0, 0, 683, 686, 1, 0, 0, 0, 684, 682, 1, 0, 0, 0, 684, 685, 1, 0, 0, 0, 685, 688, 1, 0, 0, 0, 686, 684, 1, 0, 0, 0, 687, 689, 3, 104, 52, 0, 688, 687, 1, 0, 0, 0, 688, 689, 1, 0, 0, 0, 689, 690, 1, 0, 0, 0, 690, 691, 5, 7, 0, 0, 691, 103, 1, 0, 0, 0, 692, 703, 3, 106, 53, 0, 693, 697, 5, 3, 0, 0, 694, 696, 5, 57, 0, 0, 695, 694, 1, 0, 0, 0, 696, 699, 1, 0, 0, 0, 697, 695, 1, 0, 0, 0, 697, 698, 1, 0, 0, 0, 698, 700, 1, 0, 0, 0, 699, 697, 1, 0, 0, 0, 700, 702, 3, 106, 53, 0, 701, 693, 1, 0, 0, 0, 702, 705, 1, 0, 0, 0, 703, 701, 1, 0, 0, 0, 703, 704, 1, 0, 0, 0, 704, 105, 1, 0, 0, 0, 705, 703, 1, 0, 0, 0, 706, 707, 5, 52, 0, 0, 707, 708, 5, 8, 0, 0, 708, 712, 3, 100, 50, 0, 709, 711, 5, 57, 0, 0, 710, 709, 1, 0, 0, 0, 711, 714, 1, 0, 0, 0, 712, 710, 1, 0, 0, 0, 712, 713, 1, 0, 0, 0, 713, 107, 1, 0, 0, 0, 714, 712, 1, 0, 0, 0, 715, 717, 3, 4, 2, 0, 716, 715, 1, 0, 0, 0, 716, 717, 1, 0, 0, 0, 717, 719, 1, 0, 0, 0, 718, 720, 5, 51, 0, 0, 719, 718, 1, 0, 0, 0, 719, 720, 1, 0, 0, 0, 720, 721, 1, 0, 0, 0, 721, 722, 5, 26, 0, 0, 722, 723, 3, 110, 55, 0, 723, 109, 1, 0, 0, 0, 724, 726, 3, 70, 35, 0, 725, 727, 3, 112, 56, 0, 726, 725, 1, 0, 0, 0, 726, 727, 1, 0, 0, 0, 727, 731, 1, 0, 0, 0, 728, 730, 5, 57, 0, 0, 729, 728, 1, 0, 0, 0, 730, 733, 1, 0, 0, 0, 731, 729, 1, 0, 0, 0, 731, 732, 1, 0, 0, 0, 732, 111, 1, 0, 0, 0, 733, 731, 1, 0, 0, 0, 734, 738, 5, 6, 0, 0, 735, 737, 5, 57, 0, 0, 736, 735, 1, 0, 0, 0, 737, 740, 1, 0, 0, 0, 738, 736, 1, 0, 0, 0, 738, 739, 1, 0, 0, 0, 739, 750, 1, 0, 0, 0, 740, 738, 1, 0, 0, 0, 741, 745, 5, 50, 0, 0, 742, 744, 5, 57, 0, 0, 743, 742, 1, 0, 0, 0, 744, 747, 1, 0, 0, 0, 745, 743, 1, 0, 0, 0, 745, 746, 1, 0, 0, 0, 746, 749, 1, 0, 0, 0, 747, 745, 1, 0, 0, 0, 748, 741, 1, 0, 0, 0, 749, 752, 1, 0, 0, 0, 750, 748, 1, 0, 0, 0, 750, 751, 1, 0, 0, 0, 751, 760, 1, 0, 0, 0, 752, 750, 1, 0, 0, 0, 753, 757, 3, 114, 57, 0, 754, 756, 5, 57, 0, 0, 755, 754, 1, 0, 0, 0, 756, 759, 1, 0, 0, 0, 757, 755, 1, 0, 0, 0, 757, 758, 1, 0, 0, 0, 758, 761, 1, 0, 0, 0, 759, 757, 1, 0, 0, 0, 760, 753, 1, 0, 0, 0, 760, 761, 1, 0, 0, 0, 761, 771, 1, 0, 0, 0, 762, 766, 5, 50, 0, 0, 763, 765, 5, 57, 0, 0, 764, 763, 1, 0, 0, 0, 765, 768, 1, 0, 0, 0, 766, 764, 1, 0, 0, 0, 766, 767, 1, 0, 0, 0, 767, 770, 1, 0, 0, 0, 768, 766, 1, 0, 0, 0, 769, 762, 1, 0, 0, 0, 770, 773, 1, 0, 0, 0, 771, 769, 1, 0, 0, 0, 771, 772, 1, 0, 0, 0, 772, 781, 1, 0, 0, 0, 773, 771, 1, 0, 0, 0, 774, 778, 3, 126, 63, 0, 775, 777, 5, 57, 0, 0, 776, 775, 1, 0, 0, 0, 777, 780, 1, 0, 0, 0, 778, 776, 1, 0, 0, 0, 778, 779, 1, 0, 0, 0, 779, 782, 1, 0, 0, 0, 780, 778, 1, 0, 0, 0, 781, 774, 1, 0, 0, 0, 781, 782, 1, 0, 0, 0, 782, 792, 1, 0, 0, 0, 783, 787, 5, 50, 0, 0, 784, 786, 5, 57, 0, 0, 785, 784, 1, 0, 0, 0, 786, 789, 1, 0, 0, 0, 787, 785, 1, 0, 0, 0, 787, 788, 1, 0, 0, 0, 788, 791, 1, 0, 0, 0, 789, 787, 1, 0, 0, 0, 790, 783, 1, 0, 0, 0, 791, 794, 1, 0, 0, 0, 792, 790, 1, 0, 0, 0, 792, 793, 1, 0, 0, 0, 793, 795, 1, 0, 0, 0, 794, 792, 1, 0, 0, 0, 795, 796, 5, 7, 0, 0, 796, 113, 1, 0, 0, 0, 797, 799, 3, 116, 58, 0, 798, 800, 5, 57, 0, 0, 799, 798, 1, 0, 0, 0, 800, 801, 1, 0, 0, 0, 801, 799, 1, 0, 0, 0, 801, 802, 1, 0, 0, 0, 802, 803, 1, 0, 0, 0, 803, 804, 5, 27, 0, 0, 804, 115, 1, 0, 0, 0, 805, 807, 3, 118, 59, 0, 806, 808, 5, 3, 0, 0, 807, 806, 1, 0, 0, 0, 807, 808, 1, 0, 0, 0, 808, 811, 1, 0, 0, 0, 809, 811, 5, 50, 0, 0, 810, 805, 1, 0, 0, 0, 810, 809, 1, 0, 0, 0, 811, 815, 1, 0, 0, 0, 812, 814, 5, 57, 0, 0, 813, 812, 1, 0, 0, 0, 814, 817, 1, 0, 0, 0, 815, 813, 1, 0, 0, 0, 815, 816, 1, 0, 0, 0, 816, 819, 1, 0, 0, 0, 817, 815, 1, 0, 0, 0, 818, 810, 1, 0, 0, 0, 819, 820, 1, 0, 0, 0, 820, 818, 1, 0, 0, 0, 820, 821, 1, 0, 0, 0, 821, 117, 1, 0, 0, 0, 822, 824, 3, 4, 2, 0, 823, 822, 1, 0, 0, 0, 823, 824, 1, 0, 0, 0, 824, 826, 1, 0, 0, 0, 825, 827, 5, 52, 0, 0, 826, 825, 1, 0, 0, 0, 826, 827, 1, 0, 0, 0, 827, 828, 1, 0, 0, 0, 828, 829, 3, 120, 60, 0, 829, 119, 1, 0, 0, 0, 830, 834, 3, 28, 14, 0, 831, 833, 5, 57, 0, 0, 832, 831, 1, 0, 0, 0, 833, 836, 1, 0, 0, 0, 834, 832, 1, 0, 0, 0, 834, 835, 1, 0, 0, 0, 835, 838, 1, 0, 0, 0, 836, 834, 1, 0, 0, 0, 837, 839, 3, 52, 26, 0, 838, 837, 1, 0, 0, 0, 838, 839, 1, 0, 0, 0, 839, 843, 1, 0, 0, 0, 840, 842, 5, 57, 0, 0, 841, 840, 1, 0, 0, 0, 842, 845, 1, 0, 0, 0, 843, 841, 1, 0, 0, 0, 843, 844, 1, 0, 0, 0, 844, 847, 1, 0, 0, 0, 845, 843, 1, 0, 0, 0, 846, 848, 3, 124, 62, 0, 847, 846, 1, 0, 0, 0, 847, 848, 1, 0, 0, 0, 848, 850, 1, 0, 0, 0, 849, 851, 3, 122, 61, 0, 850, 849, 1, 0, 0, 0, 850, 851, 1, 0, 0, 0, 851, 121, 1, 0, 0, 0, 852, 853, 5, 28, 0, 0, 853, 123, 1, 0, 0, 0, 854, 858, 5, 6, 0, 0, 855, 857, 5, 57, 0, 0, 856, 855, 1, 0, 0, 0, 857, 860, 1, 0, 0, 0, 858, 856, 1, 0, 0, 0, 858, 859, 1, 0, 0, 0, 859, 861, 1, 0, 0, 0, 860, 858, 1, 0, 0, 0, 861, 862, 3, 116, 58, 0, 862, 863, 5, 7, 0, 0, 863, 125, 1, 0, 0, 0, 864, 867, 3, 128, 64, 0, 865, 867, 5, 50, 0, 0, 866, 864, 1, 0, 0, 0, 866, 865, 1, 0, 0, 0, 867, 880, 1, 0, 0, 0, 868, 870, 5, 57, 0, 0, 869, 868, 1, 0, 0, 0, 870, 873, 1, 0, 0, 0, 871, 869, 1, 0, 0, 0, 871, 872, 1, 0, 0, 0, 872, 876, 1, 0, 0, 0, 873, 871, 1, 0, 0, 0, 874, 877, 3, 128, 64, 0, 875, 877, 5, 50, 0, 0, 876, 874, 1, 0, 0, 0, 876, 875, 1, 0, 0, 0, 877, 879, 1, 0, 0, 0, 878, 871, 1, 0, 0, 0, 879, 882, 1, 0, 0, 0, 880, 878, 1, 0, 0, 0, 880, 881, 1, 0, 0, 0, 881, 127, 1, 0, 0, 0, 882, 880, 1, 0, 0, 0, 883, 886, 3, 130, 65, 0, 884, 886, 3, 136, 68, 0, 885, 883, 1, 0, 0, 0, 885, 884, 1, 0, 0, 0, 886, 129, 1, 0, 0, 0, 887, 888, 3, 132, 66, 0, 888, 889, 5, 29, 0, 0, 889, 890, 3, 150, 75, 0, 890, 131, 1, 0, 0, 0, 891, 894, 3, 138, 69, 0, 892, 894, 3, 134, 67, 0, 893, 891, 1, 0, 0, 0, 893, 892, 1, 0, 0, 0, 894, 133, 1, 0, 0, 0, 895, 899, 5, 19, 0, 0, 896, 898, 5, 57, 0, 0, 897, 896, 1, 0, 0, 0, 898, 901, 1, 0, 0, 0, 899, 897, 1, 0, 0, 0, 899, 900, 1, 0, 0, 0, 900, 902, 1, 0, 0, 0, 901, 899, 1, 0, 0, 0, 902, 919, 3, 138, 69, 0, 903, 907, 5, 3, 0, 0, 904, 906, 5, 57, 0, 0, 905, 904, 1, 0, 0, 0, 906, 909, 1, 0, 0, 0, 907, 905, 1, 0, 0, 0, 907, 908, 1, 0, 0, 0, 908, 910, 1, 0, 0, 0, 909, 907, 1, 0, 0, 0, 910, 914, 3, 138, 69, 0, 911, 913, 5, 57, 0, 0, 912, 911, 1, 0, 0, 0, 913, 916, 1, 0, 0, 0, 914, 912, 1, 0, 0, 0, 914, 915, 1, 0, 0, 0, 915, 918, 1, 0, 0, 0, 916, 914, 1, 0, 0, 0, 917, 903, 1, 0, 0, 0, 918, 921, 1, 0, 0, 0, 919, 917, 1, 0, 0, 0, 919, 920, 1, 0, 0, 0, 920, 922, 1, 0, 0, 0, 921, 919, 1, 0, 0, 0, 922, 923, 5, 20, 0, 0, 923, 135, 1, 0, 0, 0, 924, 925, 3, 168, 84, 0, 925, 926, 5, 30, 0, 0, 926, 927, 3, 168, 84, 0, 927, 137, 1, 0, 0, 0, 928, 937, 3, 162, 81, 0, 929, 937, 3, 156, 78, 0, 930, 937, 3, 90, 45, 0, 931, 937, 3, 158, 79, 0, 932, 937, 3, 178, 89, 0, 933, 937, 3, 140, 70, 0, 934, 937, 3, 146, 73, 0, 935, 937, 3, 144, 72, 0, 936, 928, 1, 0, 0, 0, 936, 929, 1, 0, 0, 0, 936, 930, 1, 0, 0, 0, 936, 931, 1, 0, 0, 0, 936, 932, 1, 0, 0, 0, 936, 933, 1, 0, 0, 0, 936, 934, 1, 0, 0, 0, 936, 935, 1, 0, 0, 0, 937, 139, 1, 0, 0, 0, 938, 939, 3, 142, 71, 0, 939, 940, 3, 138, 69, 0, 940, 141, 1, 0, 0, 0, 941, 942, 7, 2, 0, 0, 942, 143, 1, 0, 0, 0, 943, 944, 5, 2, 0, 0, 944, 945, 3, 138, 69, 0, 945, 946, 5, 28, 0, 0, 946, 947, 3, 138, 69, 0, 947, 948, 5, 8, 0, 0, 948, 949, 3, 138, 69, 0, 949, 950, 5, 4, 0, 0, 950, 145, 1, 0, 0, 0, 951, 952, 5, 2, 0, 0, 952, 953, 3, 138, 69, 0, 953, 954, 3, 148, 74, 0, 954, 955, 3, 138, 69, 0, 955, 956, 5, 4, 0, 0, 956, 147, 1, 0, 0, 0, 957, 958, 7, 3, 0, 0, 958, 149, 1, 0, 0, 0, 959, 962, 3, 180, 90, 0, 960, 962, 3, 182, 91, 0, 961, 959, 1, 0, 0, 0, 961, 960, 1, 0, 0, 0, 962, 151, 1, 0, 0, 0, 963, 964, 3, 130, 65, 0, 964, 153, 1, 0, 0, 0, 965, 969, 5, 6, 0, 0, 966, 968, 5, 57, 0, 0, 967, 966, 1, 0, 0, 0, 968, 971, 1, 0, 0, 0, 969, 967, 1, 0, 0, 0, 969, 970, 1, 0, 0, 0, 970, 972, 1, 0, 0, 0, 971, 969, 1, 0, 0, 0, 972, 976, 3, 128, 64, 0, 973, 975, 5, 57, 0, 0, 974, 973, 1, 0, 0, 0, 975, 978, 1, 0, 0, 0, 976, 974, 1, 0, 0, 0, 976, 977, 1, 0, 0, 0, 977, 979, 1, 0, 0, 0, 978, 976, 1, 0, 0, 0, 979, 980, 5, 7, 0, 0, 980, 155, 1, 0, 0, 0, 981, 982, 5, 46, 0, 0, 982, 983, 3, 28, 14, 0, 983, 157, 1, 0, 0, 0, 984, 985, 3, 160, 80, 0, 985, 986, 5, 47, 0, 0, 986, 987, 3, 160, 80, 0, 987, 159, 1, 0, 0, 0, 988, 990, 5, 54, 0, 0, 989, 988, 1, 0, 0, 0, 989, 990, 1, 0, 0, 0, 990, 991, 1, 0, 0, 0, 991, 992, 5, 53, 0, 0, 992, 161, 1, 0, 0, 0, 993, 998, 3, 168, 84, 0, 994, 998, 3, 170, 85, 0, 995, 998, 3, 164, 82, 0, 996, 998, 3, 166, 83, 0, 997, 993, 1, 0, 0, 0, 997, 994, 1, 0, 0, 0, 997, 995, 1, 0, 0, 0, 997, 996, 1, 0, 0, 0, 998, 163, 1, 0, 0, 0, 999, 1000, 3, 172, 86, 0, 1000, 165, 1, 0, 0, 0, 1001, 1002, 3, 172, 86, 0, 1002, 1003, 3, 176, 88, 0, 1003, 167, 1, 0, 0, 0, 1004, 1006, 3, 172, 86, 0, 1005, 1004, 1, 0, 0, 0, 1005, 1006, 1, 0, 0, 0, 1006, 1007, 1, 0, 0, 0, 1007, 1008, 5, 8, 0, 0, 1008, 1009, 3, 174, 87, 0, 1009, 169, 1, 0, 0, 0, 1010, 1012, 3, 172, 86, 0, 1011, 1010, 1, 0, 0, 0, 1011, 1012, 1, 0, 0, 0, 1012, 1013, 1, 0, 0, 0, 1013, 1014, 5, 8, 0, 0, 1014, 1015, 3, 174, 87, 0, 1015, 1016, 3, 176, 88, 0, 1016, 171, 1, 0, 0, 0, 1017, 1018, 5, 52, 0, 0, 1018, 173, 1, 0, 0, 0, 1019, 1020, 5, 52, 0, 0, 1020, 175, 1, 0, 0, 0, 1021, 1022, 5, 19, 0, 0, 1022, 1023, 5, 53, 0, 0, 1023, 1024, 5, 20, 0, 0, 1024, 177, 1, 0, 0, 0, 1025, 1026, 5, 11, 0, 0, 1026, 1031, 5, 52, 0, 0, 1027, 1028, 5, 11, 0, 0, 1028, 1030, 5, 52, 0, 0, 1029, 1027, 1, 0, 0, 0, 1030, 1033, 1, 0, 0, 0, 1031, 1029, 1, 0, 0, 0, 1031, 1032, 1, 0, 0, 0, 1032, 179, 1, 0, 0, 0, 1033, 1031, 1, 0, 0, 0, 1034, 1039, 3, 152, 76, 0, 1035, 1039, 3, 162, 81, 0, 1036, 1039, 3, 154, 77, 0, 1037, 1039, 3, 184, 92, 0, 1038, 1034, 1, 0, 0, 0, 1038, 1035, 1, 0, 0, 0, 1038, 1036, 1, 0, 0, 0, 1038, 1037, 1, 0, 0, 0, 1039, 181, 1, 0, 0, 0, 1040, 1044, 5, 19, 0, 0, 1041, 1043, 5, 57, 0, 0, 1042, 1041, 1, 0, 0, 0, 1043, 1046, 1, 0, 0, 0, 1044, 1042, 1, 0, 0, 0, 1044, 1045, 1, 0, 0, 0, 1045, 1047, 1, 0, 0, 0, 1046, 1044, 1, 0, 0, 0, 1047, 1064, 3, 180, 90, 0, 1048, 1052, 5, 3, 0, 0, 1049, 1051, 5, 57, 0, 0, 1050, 1049, 1, 0, 0, 0, 1051, 1054, 1, 0, 0, 0, 1052, 1050, 1, 0, 0, 0, 1052, 1053, 1, 0, 0, 0, 1053, 1055, 1, 0, 0, 0, 1054, 1052, 1, 0, 0, 0, 1055, 1059, 3, 180, 90, 0, 1056, 1058, 5, 57, 0, 0, 1057, 1056, 1, 0, 0, 0, 1058, 1061, 1, 0, 0, 0, 1059, 1057, 1, 0, 0, 0, 1059, 1060, 1, 0, 0, 0, 1060, 1063, 1, 0, 0, 0, 1061, 1059, 1, 0, 0, 0, 1062, 1048, 1, 0, 0, 0, 1063, 1066, 1, 0, 0, 0, 1064, 1062, 1, 0, 0, 0, 1064, 1065, 1, 0, 0, 0, 1065, 1067, 1, 0, 0, 0, 1066, 1064, 1, 0, 0, 0, 1067, 1068, 5, 20, 0, 0, 1068, 183, 1, 0, 0, 0, 1069, 1073, 5, 48, 0, 0, 1070, 1072, 5, 57, 0, 0, 1071, 1070, 1, 0, 0, 0, 1072, 1075, 1, 0, 0, 0, 1073, 1071, 1, 0, 0, 0, 1073, 1074, 1, 0, 0, 0, 1074, 1076, 1, 0, 0, 0, 1075, 1073, 1, 0, 0, 0, 1076, 1080, 5, 6, 0, 0, 1077, 1079, 5, 57, 0, 0, 1078, 1077, 1, 0, 0, 0, 1079, 1082, 1, 0, 0, 0, 1080, 1078, 1, 0, 0, 0, 1080, 1081, 1, 0, 0, 0, 1081, 1083, 1, 0, 0, 0, 1082, 1080, 1, 0, 0, 0, 1083, 1092, 3, 130, 65, 0, 1084, 1086, 5, 57, 0, 0, 1085, 1084, 1, 0, 0, 0, 1086, 1087, 1, 0, 0, 0, 1087, 1085, 1, 0, 0, 0, 1087, 1088, 1, 0, 0, 0, 1088, 1089, 1, 0, 0, 0, 1089, 1091, 3, 130, 65, 0, 1090, 1085, 1, 0, 0, 0, 1091, 1094, 1, 0, 0, 0, 1092, 1090, 1, 0, 0, 0, 1092, 1093, 1, 0, 0, 0, 1093, 1101, 1, 0, 0, 0, 1094, 1092, 1, 0, 0, 0, 1095, 1097, 5, 57, 0, 0, 1096, 1095, 1, 0, 0, 0, 1097, 1098, 1, 0, 0, 0, 1098, 1096, 1, 0, 0, 0, 1098, 1099, 1, 0, 0, 0, 1099, 1100, 1, 0, 0, 0, 1100, 1102, 3, 186, 93, 0, 1101, 1096, 1, 0, 0, 0, 1101, 1102, 1, 0, 0, 0, 1102, 1106, 1, 0, 0, 0, 1103, 1105, 5, 57, 0, 0, 1104, 1103, 1, 0, 0, 0, 1105, 1108, 1, 0, 0, 0, 1106, 1104, 1, 0, 0, 0, 1106, 1107, 1, 0, 0, 0, 1107, 1109, 1, 0, 0, 0, 1108, 1106, 1, 0, 0, 0, 1109, 1110, 5, 7, 0, 0, 1110, 185, 1, 0, 0, 0, 1111, 1112, 5, 49, 0, 0, 1112, 1113, 5, 29, 0, 0, 1113, 1114, 3, 150, 75, 0, 1114, 187, 1, 0, 0, 0, 144, 191, 193, 203, 210, 215, 223, 231, 237, 244, 250, 256, 260, 265, 273, 279, 287, 297, 302, 315, 322, 325, 328, 334, 338, 347, 353, 358, 363, 369, 373, 379, 387, 393, 399, 406, 412, 419, 427, 433, 439, 448, 455, 459, 467, 472, 480, 487, 494, 500, 504, 507, 514, 521, 532, 536, 543, 546, 552, 557, 561, 567, 573, 580, 585, 589, 599, 604, 609, 613, 620, 624, 628, 633, 645, 649, 659, 666, 671, 674, 678, 684, 688, 697, 703, 712, 716, 719, 726, 731, 738, 745, 750, 757, 760, 766, 771, 778, 781, 787, 792, 801, 807, 810, 815, 820, 823, 826, 834, 838, 843, 847, 850, 858, 866, 871, 876, 880, 885, 893, 899, 907, 914, 919, 936, 961, 969, 976, 989, 997, 1005, 1011, 1031, 1038, 1044, 1052, 1059, 1064, 1073, 1080, 1087, 1092, 1098, 1101, 1106] \ No newline at end of file diff --git a/internal/compiler/parser/generated/neva_parser.go b/internal/compiler/parser/generated/neva_parser.go index 39ae4e3c..7fe75ac3 100644 --- a/internal/compiler/parser/generated/neva_parser.go +++ b/internal/compiler/parser/generated/neva_parser.go @@ -130,7 +130,7 @@ func nevaParserInit() { 38, 1, 38, 3, 38, 537, 8, 38, 1, 38, 1, 38, 1, 38, 5, 38, 542, 8, 38, 10, 38, 12, 38, 545, 9, 38, 3, 38, 547, 8, 38, 1, 38, 1, 38, 1, 39, 1, 39, 3, 39, 553, 8, 39, 1, 40, 5, 40, 556, 8, 40, 10, 40, 12, 40, 559, 9, 40, - 1, 40, 1, 40, 3, 40, 563, 8, 40, 1, 40, 5, 40, 566, 8, 40, 10, 40, 12, + 1, 40, 3, 40, 562, 8, 40, 1, 40, 1, 40, 5, 40, 566, 8, 40, 10, 40, 12, 40, 569, 9, 40, 1, 41, 5, 41, 572, 8, 41, 10, 41, 12, 41, 575, 9, 41, 1, 41, 1, 41, 1, 41, 1, 41, 3, 41, 581, 8, 41, 1, 41, 5, 41, 584, 8, 41, 10, 41, 12, 41, 587, 9, 41, 1, 42, 3, 42, 590, 8, 42, 1, 42, 1, 42, 1, 42, @@ -363,9 +363,9 @@ func nevaParserInit() { 0, 0, 549, 77, 1, 0, 0, 0, 550, 553, 3, 80, 40, 0, 551, 553, 3, 82, 41, 0, 552, 550, 1, 0, 0, 0, 552, 551, 1, 0, 0, 0, 553, 79, 1, 0, 0, 0, 554, 556, 5, 57, 0, 0, 555, 554, 1, 0, 0, 0, 556, 559, 1, 0, 0, 0, 557, 555, - 1, 0, 0, 0, 557, 558, 1, 0, 0, 0, 558, 560, 1, 0, 0, 0, 559, 557, 1, 0, - 0, 0, 560, 562, 5, 52, 0, 0, 561, 563, 3, 48, 24, 0, 562, 561, 1, 0, 0, - 0, 562, 563, 1, 0, 0, 0, 563, 567, 1, 0, 0, 0, 564, 566, 5, 57, 0, 0, 565, + 1, 0, 0, 0, 557, 558, 1, 0, 0, 0, 558, 561, 1, 0, 0, 0, 559, 557, 1, 0, + 0, 0, 560, 562, 5, 52, 0, 0, 561, 560, 1, 0, 0, 0, 561, 562, 1, 0, 0, 0, + 562, 563, 1, 0, 0, 0, 563, 567, 3, 48, 24, 0, 564, 566, 5, 57, 0, 0, 565, 564, 1, 0, 0, 0, 566, 569, 1, 0, 0, 0, 567, 565, 1, 0, 0, 0, 567, 568, 1, 0, 0, 0, 568, 81, 1, 0, 0, 0, 569, 567, 1, 0, 0, 0, 570, 572, 5, 57, 0, 0, 571, 570, 1, 0, 0, 0, 572, 575, 1, 0, 0, 0, 573, 571, 1, 0, 0, 0, @@ -575,7 +575,7 @@ func nevaParserInit() { 223, 231, 237, 244, 250, 256, 260, 265, 273, 279, 287, 297, 302, 315, 322, 325, 328, 334, 338, 347, 353, 358, 363, 369, 373, 379, 387, 393, 399, 406, 412, 419, 427, 433, 439, 448, 455, 459, 467, 472, 480, 487, 494, 500, 504, - 507, 514, 521, 532, 536, 543, 546, 552, 557, 562, 567, 573, 580, 585, 589, + 507, 514, 521, 532, 536, 543, 546, 552, 557, 561, 567, 573, 580, 585, 589, 599, 604, 609, 613, 620, 624, 628, 633, 645, 649, 659, 666, 671, 674, 678, 684, 688, 697, 703, 712, 716, 719, 726, 731, 738, 745, 750, 757, 760, 766, 771, 778, 781, 787, 792, 801, 807, 810, 815, 820, 823, 826, 834, 838, 843, @@ -6995,7 +6995,7 @@ func (p *nevaParser) PortsDef() (localctx IPortsDefContext) { } _la = p.GetTokenStream().LA(1) - if (int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&148618787703750656) != 0 { + if (int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&148618787703848960) != 0 { { p.SetState(535) p.PortDef() @@ -7210,10 +7210,10 @@ type ISinglePortDefContext interface { GetParser() antlr.Parser // Getter signatures - IDENTIFIER() antlr.TerminalNode + TypeExpr() ITypeExprContext AllNEWLINE() []antlr.TerminalNode NEWLINE(i int) antlr.TerminalNode - TypeExpr() ITypeExprContext + IDENTIFIER() antlr.TerminalNode // IsSinglePortDefContext differentiates from other interfaces. IsSinglePortDefContext() @@ -7251,18 +7251,6 @@ func NewSinglePortDefContext(parser antlr.Parser, parent antlr.ParserRuleContext func (s *SinglePortDefContext) GetParser() antlr.Parser { return s.parser } -func (s *SinglePortDefContext) IDENTIFIER() antlr.TerminalNode { - return s.GetToken(nevaParserIDENTIFIER, 0) -} - -func (s *SinglePortDefContext) AllNEWLINE() []antlr.TerminalNode { - return s.GetTokens(nevaParserNEWLINE) -} - -func (s *SinglePortDefContext) NEWLINE(i int) antlr.TerminalNode { - return s.GetToken(nevaParserNEWLINE, i) -} - func (s *SinglePortDefContext) TypeExpr() ITypeExprContext { var t antlr.RuleContext for _, ctx := range s.GetChildren() { @@ -7279,6 +7267,18 @@ func (s *SinglePortDefContext) TypeExpr() ITypeExprContext { return t.(ITypeExprContext) } +func (s *SinglePortDefContext) AllNEWLINE() []antlr.TerminalNode { + return s.GetTokens(nevaParserNEWLINE) +} + +func (s *SinglePortDefContext) NEWLINE(i int) antlr.TerminalNode { + return s.GetToken(nevaParserNEWLINE, i) +} + +func (s *SinglePortDefContext) IDENTIFIER() antlr.TerminalNode { + return s.GetToken(nevaParserIDENTIFIER, 0) +} + func (s *SinglePortDefContext) GetRuleContext() antlr.RuleContext { return s } @@ -7329,27 +7329,25 @@ func (p *nevaParser) SinglePortDef() (localctx ISinglePortDefContext) { } _la = p.GetTokenStream().LA(1) } - { - p.SetState(560) - p.Match(nevaParserIDENTIFIER) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - p.SetState(562) + p.SetState(561) p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - _la = p.GetTokenStream().LA(1) - if (int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&4503599627468800) != 0 { + if p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 59, p.GetParserRuleContext()) == 1 { { - p.SetState(561) - p.TypeExpr() + p.SetState(560) + p.Match(nevaParserIDENTIFIER) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } } + } else if p.HasError() { // JIM + goto errorExit + } + { + p.SetState(563) + p.TypeExpr() } p.SetState(567) p.GetErrorHandler().Sync(p) diff --git a/internal/compiler/parser/listener.go b/internal/compiler/parser/listener.go index 2be0001d..2689e899 100644 --- a/internal/compiler/parser/listener.go +++ b/internal/compiler/parser/listener.go @@ -1,88 +1,63 @@ package parser import ( - "strings" - generated "github.com/nevalang/neva/internal/compiler/parser/generated" src "github.com/nevalang/neva/internal/compiler/sourcecode" "github.com/nevalang/neva/internal/compiler/sourcecode/core" ) +type treeShapeListener struct { + *generated.BasenevaListener + loc core.Location + state src.File +} + func (s *treeShapeListener) EnterProg(actx *generated.ProgContext) { - s.file.Entities = map[string]src.Entity{} - s.file.Imports = map[string]src.Import{} + s.state.Entities = map[string]src.Entity{} + s.state.Imports = map[string]src.Import{} } func (s *treeShapeListener) EnterImportDef(actx *generated.ImportDefContext) { - path := actx.ImportPath() - pkgName := path.ImportPathPkg().GetText() - - var modName string - if path.ImportPathMod() != nil { - modName = path.ImportPathMod().GetText() - } else { - modName = "std" - } - - var alias string - if tmp := actx.ImportAlias(); tmp != nil { - alias = tmp.GetText() - } else { - parts := strings.Split(pkgName, "/") - alias = parts[len(parts)-1] - } - - s.file.Imports[alias] = src.Import{ - Module: modName, - Package: pkgName, - Meta: core.Meta{ - Text: actx.GetText(), - Start: core.Position{ - Line: actx.GetStart().GetLine(), - Column: actx.GetStart().GetColumn(), - }, - Stop: core.Position{ - Line: actx.GetStop().GetLine(), - Column: actx.GetStop().GetColumn(), - }, - }, + imp, alias, err := s.parseImport(actx) + if err != nil { + panic(err) } + s.state.Imports[alias] = imp } func (s *treeShapeListener) EnterTypeStmt(actx *generated.TypeStmtContext) { typeDef := actx.TypeDef() - v, err := parseTypeDef(typeDef) + parsedEntity, err := s.parseTypeDef(typeDef) if err != nil { panic(err) } - parsedEntity := v parsedEntity.IsPublic = actx.PUB_KW() != nil name := typeDef.IDENTIFIER().GetText() - s.file.Entities[name] = parsedEntity + s.state.Entities[name] = parsedEntity } func (s *treeShapeListener) EnterConstStmt(actx *generated.ConstStmtContext) { constDef := actx.ConstDef() - parsedEntity, err := parseConstDef(constDef) + parsedEntity, err := s.parseConstDef(constDef) if err != nil { panic(err) } parsedEntity.IsPublic = actx.PUB_KW() != nil name := constDef.IDENTIFIER().GetText() - s.file.Entities[name] = parsedEntity + s.state.Entities[name] = parsedEntity } func (s *treeShapeListener) EnterInterfaceStmt(actx *generated.InterfaceStmtContext) { name := actx.InterfaceDef().IDENTIFIER().GetText() - v, err := parseInterfaceDef(actx.InterfaceDef()) + v, err := s.parseInterfaceDef(actx.InterfaceDef()) if err != nil { panic(err) } - s.file.Entities[name] = src.Entity{ + s.state.Entities[name] = src.Entity{ IsPublic: actx.PUB_KW() != nil, Kind: src.InterfaceEntity, Interface: v, @@ -92,15 +67,15 @@ func (s *treeShapeListener) EnterInterfaceStmt(actx *generated.InterfaceStmtCont func (s *treeShapeListener) EnterCompStmt(actx *generated.CompStmtContext) { compDef := actx.CompDef() - parsedCompEntity, err := parseCompDef(compDef) + parsedCompEntity, err := s.parseCompDef(compDef) if err != nil { panic(err) } parsedCompEntity.IsPublic = actx.PUB_KW() != nil - parsedCompEntity.Component.Directives = parseCompilerDirectives( + parsedCompEntity.Component.Directives = s.parseCompilerDirectives( actx.CompilerDirectives(), ) name := compDef.InterfaceDef().IDENTIFIER().GetText() - s.file.Entities[name] = parsedCompEntity + s.state.Entities[name] = parsedCompEntity } diff --git a/internal/compiler/parser/listener_helpers.go b/internal/compiler/parser/listener_helpers.go index ac740d13..2b0775dd 100644 --- a/internal/compiler/parser/listener_helpers.go +++ b/internal/compiler/parser/listener_helpers.go @@ -13,7 +13,44 @@ import ( ts "github.com/nevalang/neva/internal/compiler/sourcecode/typesystem" ) -func parseTypeParams( +func (s *treeShapeListener) parseImport(actx generated.IImportDefContext) (src.Import, string, *compiler.Error) { + path := actx.ImportPath() + pkgName := path.ImportPathPkg().GetText() + + var modName string + if path.ImportPathMod() != nil { + modName = path.ImportPathMod().GetText() + } else { + modName = "std" + } + + var alias string + if tmp := actx.ImportAlias(); tmp != nil { + alias = tmp.GetText() + } else { + parts := strings.Split(pkgName, "/") + alias = parts[len(parts)-1] + } + + return src.Import{ + Module: modName, + Package: pkgName, + Meta: core.Meta{ + Text: actx.GetText(), + Start: core.Position{ + Line: actx.GetStart().GetLine(), + Column: actx.GetStart().GetColumn(), + }, + Stop: core.Position{ + Line: actx.GetStop().GetLine(), + Column: actx.GetStop().GetColumn(), + }, + Location: s.loc, + }, + }, alias, nil +} + +func (s *treeShapeListener) parseTypeParams( params generated.ITypeParamsContext, ) (src.TypeParams, *compiler.Error) { if params == nil || params.TypeParamList() == nil { @@ -23,7 +60,7 @@ func parseTypeParams( typeParams := params.TypeParamList().AllTypeParam() result := make([]ts.Param, 0, len(typeParams)) for _, typeParam := range typeParams { - v, err := parseTypeExpr(typeParam.TypeExpr()) + v, err := s.parseTypeExpr(typeParam.TypeExpr()) if err != nil { return src.TypeParams{}, err } @@ -45,23 +82,27 @@ func parseTypeParams( Line: params.GetStop().GetLine(), Column: params.GetStop().GetColumn(), }, + Location: s.loc, }, }, nil } -func parseTypeExpr(expr generated.ITypeExprContext) (ts.Expr, *compiler.Error) { +func (s *treeShapeListener) parseTypeExpr(expr generated.ITypeExprContext) (ts.Expr, *compiler.Error) { if expr == nil { return ts.Expr{ Inst: &ts.InstExpr{ Ref: core.EntityRef{Name: "any"}, }, - Meta: core.Meta{Text: "any"}, + Meta: core.Meta{ + Text: "any", + Location: s.loc, + }, }, nil } var result *ts.Expr if instExpr := expr.TypeInstExpr(); instExpr != nil { - v, err := parseTypeInstExpr(instExpr) + v, err := s.parseTypeInstExpr(instExpr) if err != nil { return ts.Expr{}, &compiler.Error{ Message: err.Error(), @@ -75,18 +116,19 @@ func parseTypeExpr(expr generated.ITypeExprContext) (ts.Expr, *compiler.Error) { Line: expr.GetStop().GetLine(), Column: expr.GetStop().GetColumn(), }, + Location: s.loc, }, } } result = v } else if unionExpr := expr.UnionTypeExpr(); unionExpr != nil { - v, err := parseUnionExpr(unionExpr) + v, err := s.parseUnionExpr(unionExpr) if err != nil { return ts.Expr{}, err } result = v } else if litExpr := expr.TypeLitExpr(); litExpr != nil { - v, err := parseLitExpr(litExpr) + v, err := s.parseLitExpr(litExpr) if err != nil { return ts.Expr{}, err } @@ -104,16 +146,17 @@ func parseTypeExpr(expr generated.ITypeExprContext) (ts.Expr, *compiler.Error) { Line: expr.GetStop().GetLine(), Column: expr.GetStop().GetLine(), }, + Location: s.loc, }, } } - result.Meta = getTypeExprMeta(expr) + result.Meta = s.getTypeExprMeta(expr) return *result, nil } -func getTypeExprMeta(expr generated.ITypeExprContext) core.Meta { +func (s *treeShapeListener) getTypeExprMeta(expr generated.ITypeExprContext) core.Meta { var text string if text = expr.GetText(); text == "" { text = "any " @@ -131,24 +174,25 @@ func getTypeExprMeta(expr generated.ITypeExprContext) core.Meta { Line: stop.GetLine(), Column: stop.GetColumn(), }, + Location: s.loc, } return meta } -func parseUnionExpr(unionExpr generated.IUnionTypeExprContext) (*ts.Expr, *compiler.Error) { +func (s *treeShapeListener) parseUnionExpr(unionExpr generated.IUnionTypeExprContext) (*ts.Expr, *compiler.Error) { subExprs := unionExpr.AllNonUnionTypeExpr() parsedSubExprs := make([]ts.Expr, 0, len(subExprs)) for _, subExpr := range subExprs { if instExpr := subExpr.TypeInstExpr(); instExpr != nil { - parsedTypeInstExpr, err := parseTypeInstExpr(instExpr) + parsedTypeInstExpr, err := s.parseTypeInstExpr(instExpr) if err != nil { return nil, err } parsedSubExprs = append(parsedSubExprs, *parsedTypeInstExpr) } if unionExpr := subExpr.TypeLitExpr(); unionExpr != nil { - v, err := parseLitExpr(subExpr.TypeLitExpr()) + v, err := s.parseLitExpr(subExpr.TypeLitExpr()) if err != nil { return nil, err } @@ -170,19 +214,20 @@ func parseUnionExpr(unionExpr generated.IUnionTypeExprContext) (*ts.Expr, *compi Line: unionExpr.GetStop().GetLine(), Column: unionExpr.GetStop().GetColumn(), }, + Location: s.loc, }, }, nil } -func parseLitExpr(litExpr generated.ITypeLitExprContext) (*ts.Expr, *compiler.Error) { +func (s *treeShapeListener) parseLitExpr(litExpr generated.ITypeLitExprContext) (*ts.Expr, *compiler.Error) { enumExpr := litExpr.EnumTypeExpr() structExpr := litExpr.StructTypeExpr() switch { case enumExpr != nil: - return parseEnumExpr(enumExpr), nil + return s.parseEnumExpr(enumExpr), nil case structExpr != nil: - return parseStructExpr(structExpr) + return s.parseStructExpr(structExpr) } return nil, &compiler.Error{ @@ -197,11 +242,12 @@ func parseLitExpr(litExpr generated.ITypeLitExprContext) (*ts.Expr, *compiler.Er Line: litExpr.GetStop().GetLine(), Column: litExpr.GetStop().GetColumn(), }, + Location: s.loc, }, } } -func parseEnumExpr(enumExpr generated.IEnumTypeExprContext) *ts.Expr { +func (s *treeShapeListener) parseEnumExpr(enumExpr generated.IEnumTypeExprContext) *ts.Expr { ids := enumExpr.AllIDENTIFIER() result := ts.Expr{ Lit: &ts.LitExpr{ @@ -221,11 +267,12 @@ func parseEnumExpr(enumExpr generated.IEnumTypeExprContext) *ts.Expr { Line: enumExpr.GetStop().GetLine(), Column: enumExpr.GetStop().GetColumn(), }, + Location: s.loc, } return &result } -func parseStructExpr( +func (s *treeShapeListener) parseStructExpr( structExpr generated.IStructTypeExprContext, ) (*ts.Expr, *compiler.Error) { result := ts.Expr{ @@ -244,7 +291,7 @@ func parseStructExpr( for _, field := range fields { fieldName := field.IDENTIFIER().GetText() - v, err := parseTypeExpr(field.TypeExpr()) + v, err := s.parseTypeExpr(field.TypeExpr()) if err != nil { return nil, err } @@ -261,13 +308,14 @@ func parseStructExpr( Line: structExpr.GetStop().GetLine(), Column: structExpr.GetStop().GetColumn(), }, + Location: s.loc, } return &result, nil } -func parseTypeInstExpr(instExpr generated.ITypeInstExprContext) (*ts.Expr, *compiler.Error) { - parsedRef, err := parseEntityRef(instExpr.EntityRef()) +func (s *treeShapeListener) parseTypeInstExpr(instExpr generated.ITypeInstExprContext) (*ts.Expr, *compiler.Error) { + parsedRef, err := s.parseEntityRef(instExpr.EntityRef()) if err != nil { return nil, &compiler.Error{ Message: err.Error(), @@ -281,6 +329,7 @@ func parseTypeInstExpr(instExpr generated.ITypeInstExprContext) (*ts.Expr, *comp Line: instExpr.GetStop().GetLine(), Column: instExpr.GetStop().GetColumn(), }, + Location: s.loc, }, } } @@ -299,7 +348,7 @@ func parseTypeInstExpr(instExpr generated.ITypeInstExprContext) (*ts.Expr, *comp argExprs := args.AllTypeExpr() parsedArgs := make([]ts.Expr, 0, len(argExprs)) for _, arg := range argExprs { - v, err := parseTypeExpr(arg) + v, err := s.parseTypeExpr(arg) if err != nil { return nil, err } @@ -317,12 +366,13 @@ func parseTypeInstExpr(instExpr generated.ITypeInstExprContext) (*ts.Expr, *comp Line: instExpr.GetStop().GetLine(), Column: instExpr.GetStop().GetColumn(), }, + Location: s.loc, } return &result, nil } -func parseEntityRef(expr generated.IEntityRefContext) (core.EntityRef, *compiler.Error) { +func (s *treeShapeListener) parseEntityRef(expr generated.IEntityRefContext) (core.EntityRef, *compiler.Error) { meta := core.Meta{ Text: expr.GetText(), Start: core.Position{ @@ -333,6 +383,7 @@ func parseEntityRef(expr generated.IEntityRefContext) (core.EntityRef, *compiler Line: expr.GetStart().GetLine(), Column: expr.GetStop().GetColumn(), }, + Location: s.loc, } parts := strings.Split(expr.GetText(), ".") @@ -357,7 +408,7 @@ func parseEntityRef(expr generated.IEntityRefContext) (core.EntityRef, *compiler }, nil } -func parsePorts( +func (s *treeShapeListener) parsePorts( in []generated.IPortDefContext, ) (map[string]src.Port, *compiler.Error) { parsedInports := map[string]src.Port{} @@ -380,8 +431,12 @@ func parsePorts( typeExpr = arr.TypeExpr() } - portName := id.GetText() - v, err := parseTypeExpr(typeExpr) + var portName string + if id != nil { + portName = id.GetText() + } + + v, err := s.parseTypeExpr(typeExpr) if err != nil { return nil, err } @@ -398,6 +453,7 @@ func parsePorts( Line: port.GetStop().GetLine(), Column: port.GetStop().GetColumn(), }, + Location: s.loc, }, } } @@ -405,40 +461,47 @@ func parsePorts( return parsedInports, nil } -func parseInterfaceDef( +func (s *treeShapeListener) parseInterfaceDef( actx generated.IInterfaceDefContext, ) (src.Interface, *compiler.Error) { - parsedTypeParams, err := parseTypeParams(actx.TypeParams()) + parsedTypeParams, err := s.parseTypeParams(actx.TypeParams()) if err != nil { return src.Interface{}, err } - in, err := parsePorts(actx.InPortsDef().PortsDef().AllPortDef()) + in, err := s.parsePorts(actx.InPortsDef().PortsDef().AllPortDef()) if err != nil { return src.Interface{}, err } - out, err := parsePorts(actx.OutPortsDef().PortsDef().AllPortDef()) + out, err := s.parsePorts(actx.OutPortsDef().PortsDef().AllPortDef()) if err != nil { return src.Interface{}, err } + meta := core.Meta{ + Text: actx.GetText(), + Start: core.Position{ + Line: actx.GetStart().GetLine(), + Column: actx.GetStart().GetColumn(), + }, + Stop: core.Position{ + Line: actx.GetStop().GetLine(), + Column: actx.GetStop().GetColumn(), + }, + Location: s.loc, + } + return src.Interface{ TypeParams: parsedTypeParams, - IO: src.IO{In: in, Out: out}, - Meta: core.Meta{ - Text: actx.GetText(), - Start: core.Position{ - Line: actx.GetStart().GetLine(), - Column: actx.GetStart().GetColumn(), - }, - Stop: core.Position{ - Line: actx.GetStop().GetLine(), - Column: actx.GetStop().GetColumn(), - }, + IO: src.IO{ + In: in, + Out: out, + Meta: meta, }, + Meta: meta, }, nil } -func parseNodes( +func (s *treeShapeListener) parseNodes( actx generated.ICompNodesDefBodyContext, isRootLevel bool, ) (map[string]src.Node, *compiler.Error) { @@ -447,9 +510,9 @@ func parseNodes( for _, node := range actx.AllCompNodeDef() { nodeInst := node.NodeInst() - directives := parseCompilerDirectives(node.CompilerDirectives()) + directives := s.parseCompilerDirectives(node.CompilerDirectives()) - parsedRef, err := parseEntityRef(nodeInst.EntityRef()) + parsedRef, err := s.parseEntityRef(nodeInst.EntityRef()) if err != nil { return nil, &compiler.Error{ Message: err.Error(), @@ -463,13 +526,14 @@ func parseNodes( Line: node.GetStop().GetLine(), Column: node.GetStop().GetColumn(), }, + Location: s.loc, }, } } var typeArgs []ts.Expr if args := nodeInst.TypeArgs(); args != nil { - v, err := parseTypeExprs(args.AllTypeExpr()) + v, err := s.parseTypeExprs(args.AllTypeExpr()) if err != nil { return nil, err } @@ -483,7 +547,7 @@ func parseNodes( var deps map[string]src.Node if diArgs := nodeInst.NodeDIArgs(); diArgs != nil { - v, err := parseNodes(diArgs.CompNodesDefBody(), false) + v, err := s.parseNodes(diArgs.CompNodesDefBody(), false) if err != nil { return nil, err } @@ -513,6 +577,7 @@ func parseNodes( Line: node.GetStop().GetLine(), Column: node.GetStop().GetColumn(), }, + Location: s.loc, }, } } @@ -520,13 +585,13 @@ func parseNodes( return result, nil } -func parseTypeExprs( +func (s *treeShapeListener) parseTypeExprs( in []generated.ITypeExprContext, ) ([]ts.Expr, *compiler.Error) { result := make([]ts.Expr, 0, len(in)) for _, expr := range in { - v, err := parseTypeExpr(expr) + v, err := s.parseTypeExpr(expr) if err != nil { return nil, err } @@ -536,7 +601,7 @@ func parseTypeExprs( return result, nil } -func parsePortAddr( +func (s *treeShapeListener) parsePortAddr( expr generated.IPortAddrContext, fallbackNode string, ) (src.PortAddr, *compiler.Error) { @@ -550,6 +615,7 @@ func parsePortAddr( Line: expr.GetStart().GetLine(), Column: expr.GetStop().GetColumn(), }, + Location: s.loc, } if expr.ArrPortAddr() == nil && @@ -598,7 +664,7 @@ func parsePortAddr( } if expr.SinglePortAddr() != nil { - return parseSinglePortAddr(fallbackNode, expr.SinglePortAddr(), meta) + return s.parseSinglePortAddr(fallbackNode, expr.SinglePortAddr(), meta) } idxStr := expr.ArrPortAddr().PortAddrIdx() @@ -632,7 +698,7 @@ func parsePortAddr( } -func parseSinglePortAddr( +func (s *treeShapeListener) parseSinglePortAddr( fallbackNode string, expr generated.ISinglePortAddrContext, meta core.Meta, @@ -649,7 +715,7 @@ func parseSinglePortAddr( }, nil } -func parsePrimitiveConstLiteral( +func (s *treeShapeListener) parsePrimitiveConstLiteral( lit generated.IPrimitiveConstLitContext, ) (src.Const, *compiler.Error) { parsedConst := src.Const{ @@ -666,6 +732,7 @@ func parsePrimitiveConstLiteral( Line: lit.GetStop().GetLine(), Column: lit.GetStop().GetColumn(), }, + Location: s.loc, }, } @@ -685,6 +752,7 @@ func parsePrimitiveConstLiteral( Line: lit.GetStop().GetLine(), Column: lit.GetStop().GetColumn(), }, + Location: s.loc, }, } } @@ -707,6 +775,7 @@ func parsePrimitiveConstLiteral( Line: lit.GetStop().GetLine(), Column: lit.GetStop().GetColumn(), }, + Location: s.loc, }, } } @@ -732,6 +801,7 @@ func parsePrimitiveConstLiteral( Line: lit.GetStop().GetLine(), Column: lit.GetStop().GetColumn(), }, + Location: s.loc, }, } } @@ -757,7 +827,7 @@ func parsePrimitiveConstLiteral( Ref: core.EntityRef{Name: "string"}, } case lit.EnumLit() != nil: - parsedEnumRef, err := parseEntityRef(lit.EnumLit().EntityRef()) + parsedEnumRef, err := s.parseEntityRef(lit.EnumLit().EntityRef()) if err != nil { return src.Const{}, err } @@ -776,7 +846,7 @@ func parsePrimitiveConstLiteral( return parsedConst, nil } -func parseMessage( +func (s *treeShapeListener) parseMessage( constVal generated.IConstLitContext, ) (src.MsgLiteral, *compiler.Error) { msg := src.MsgLiteral{ @@ -790,6 +860,7 @@ func parseMessage( Line: constVal.GetStop().GetLine(), Column: constVal.GetStop().GetColumn(), }, + Location: s.loc, }, } @@ -809,6 +880,7 @@ func parseMessage( Line: constVal.GetStop().GetLine(), Column: constVal.GetStop().GetColumn(), }, + Location: s.loc, }, } } @@ -828,6 +900,7 @@ func parseMessage( Line: constVal.GetStop().GetLine(), Column: constVal.GetStop().GetColumn(), }, + Location: s.loc, }, } } @@ -850,6 +923,7 @@ func parseMessage( Line: constVal.GetStop().GetLine(), Column: constVal.GetStop().GetColumn(), }, + Location: s.loc, }, } } @@ -869,7 +943,7 @@ func parseMessage( ), ) case constVal.EnumLit() != nil: - parsedEnumRef, err := parseEntityRef(constVal.EnumLit().EntityRef()) + parsedEnumRef, err := s.parseEntityRef(constVal.EnumLit().EntityRef()) if err != nil { return src.MsgLiteral{}, err } @@ -897,16 +971,17 @@ func parseMessage( Line: item.GetStop().GetLine(), Column: item.GetStop().GetLine(), }, + Location: s.loc, }, } if item.EntityRef() != nil { - parsedRef, err := parseEntityRef(item.EntityRef()) + parsedRef, err := s.parseEntityRef(item.EntityRef()) if err != nil { return src.MsgLiteral{}, err } constant.Value.Ref = &parsedRef } else { - parsedConstValue, err := parseMessage(item.ConstLit()) + parsedConstValue, err := s.parseMessage(item.ConstLit()) if err != nil { return src.MsgLiteral{}, err } @@ -929,7 +1004,7 @@ func parseMessage( } name := field.IDENTIFIER().GetText() if field.CompositeItem().EntityRef() != nil { - parsedRef, err := parseEntityRef(field.CompositeItem().EntityRef()) + parsedRef, err := s.parseEntityRef(field.CompositeItem().EntityRef()) if err != nil { return src.MsgLiteral{}, err } @@ -937,7 +1012,7 @@ func parseMessage( Ref: &parsedRef, } } else { - value, err := parseMessage(field.CompositeItem().ConstLit()) + value, err := s.parseMessage(field.CompositeItem().ConstLit()) if err != nil { return src.MsgLiteral{}, err } @@ -953,7 +1028,7 @@ func parseMessage( return msg, nil } -func parseCompilerDirectives(actx generated.ICompilerDirectivesContext) map[src.Directive][]string { +func (s *treeShapeListener) parseCompilerDirectives(actx generated.ICompilerDirectivesContext) map[src.Directive][]string { if actx == nil { return nil } @@ -985,19 +1060,19 @@ func parseCompilerDirectives(actx generated.ICompilerDirectivesContext) map[src. return result } -func parseTypeDef( +func (s *treeShapeListener) parseTypeDef( actx generated.ITypeDefContext, ) (src.Entity, *compiler.Error) { var body *ts.Expr if expr := actx.TypeExpr(); expr != nil { - v, err := parseTypeExpr(actx.TypeExpr()) + v, err := s.parseTypeExpr(actx.TypeExpr()) if err != nil { return src.Entity{}, err } body = compiler.Pointer(v) } - v, err := parseTypeParams(actx.TypeParams()) + v, err := s.parseTypeParams(actx.TypeParams()) if err != nil { return src.Entity{}, err } @@ -1018,12 +1093,13 @@ func parseTypeDef( Line: actx.GetStop().GetLine(), Column: actx.GetStop().GetColumn(), }, + Location: s.loc, }, }, }, nil } -func parseConstDef( +func (s *treeShapeListener) parseConstDef( actx generated.IConstDefContext, ) (src.Entity, *compiler.Error) { constLit := actx.ConstLit() @@ -1043,9 +1119,10 @@ func parseConstDef( Line: actx.GetStop().GetLine(), Column: actx.GetStop().GetColumn(), }, + Location: s.loc, } - parsedTypeExpr, err := parseTypeExpr(actx.TypeExpr()) + parsedTypeExpr, err := s.parseTypeExpr(actx.TypeExpr()) if err != nil { return src.Entity{}, &compiler.Error{ Message: err.Error(), @@ -1059,7 +1136,7 @@ func parseConstDef( } if entityRef != nil { - parsedRef, err := parseEntityRef(entityRef) + parsedRef, err := s.parseEntityRef(entityRef) if err != nil { return src.Entity{}, &compiler.Error{ Message: err.Error(), @@ -1073,7 +1150,7 @@ func parseConstDef( }, nil } - parsedMsgLit, err := parseMessage(constLit) + parsedMsgLit, err := s.parseMessage(constLit) if err != nil { return src.Entity{}, &compiler.Error{ Message: err.Error(), @@ -1095,8 +1172,8 @@ func parseConstDef( }, nil } -func parseCompDef(actx generated.ICompDefContext) (src.Entity, *compiler.Error) { - parsedInterfaceDef, err := parseInterfaceDef(actx.InterfaceDef()) +func (s *treeShapeListener) parseCompDef(actx generated.ICompDefContext) (src.Entity, *compiler.Error) { + parsedInterfaceDef, err := s.parseInterfaceDef(actx.InterfaceDef()) if err != nil { return src.Entity{}, err } @@ -1114,7 +1191,7 @@ func parseCompDef(actx generated.ICompDefContext) (src.Entity, *compiler.Error) parsedConnections := []src.Connection{} connections := actx.CompBody().ConnDefList() if connections != nil { - parsedNet, err := parseConnections(connections) + parsedNet, err := s.parseConnections(connections) if err != nil { return src.Entity{}, err } @@ -1133,7 +1210,7 @@ func parseCompDef(actx generated.ICompDefContext) (src.Entity, *compiler.Error) } var parsedNodes map[string]src.Node - v, err := parseNodes(nodesDef.CompNodesDefBody(), true) + v, err := s.parseNodes(nodesDef.CompNodesDefBody(), true) if err != nil { return src.Entity{}, err } @@ -1155,7 +1232,678 @@ func parseCompDef(actx generated.ICompDefContext) (src.Entity, *compiler.Error) Line: actx.GetStop().GetLine(), Column: actx.GetStop().GetColumn(), }, + Location: s.loc, }, }, }, nil } + +func (s *treeShapeListener) parseConnections(actx generated.IConnDefListContext) ([]src.Connection, *compiler.Error) { + allConnDefs := actx.AllConnDef() + parsedConns := make([]src.Connection, 0, len(allConnDefs)) + + for _, connDef := range allConnDefs { + parsedConnection, err := s.parseConnection(connDef) + if err != nil { + return nil, err + } + parsedConns = append(parsedConns, parsedConnection) + } + + return parsedConns, nil +} + +func (s *treeShapeListener) parseConnection(connDef generated.IConnDefContext) (src.Connection, *compiler.Error) { + meta := core.Meta{ + Text: connDef.GetText(), + Start: core.Position{ + Line: connDef.GetStart().GetLine(), + Column: connDef.GetStart().GetColumn(), + }, + Stop: core.Position{ + Line: connDef.GetStop().GetLine(), + Column: connDef.GetStop().GetColumn(), + }, + Location: s.loc, + } + + normConn := connDef.NormConnDef() + arrBypassConn := connDef.ArrBypassConnDef() + + if normConn == nil && arrBypassConn == nil { + return src.Connection{}, &compiler.Error{ + Message: "Connection must be either normal or array bypass", + Meta: &meta, + } + } + + if arrBypassConn != nil { + return s.parseArrayBypassConn(arrBypassConn) + } + + return s.parseNormConn(normConn) +} + +func (s *treeShapeListener) parseArrayBypassConn( + arrBypassConn generated.IArrBypassConnDefContext, +) (src.Connection, *compiler.Error) { + senderPortAddr := arrBypassConn.SinglePortAddr(0) + receiverPortAddr := arrBypassConn.SinglePortAddr(1) + + meta := core.Meta{ + Text: arrBypassConn.GetText(), + Start: core.Position{ + Line: arrBypassConn.GetStart().GetLine(), + Column: arrBypassConn.GetStart().GetColumn(), + }, + Stop: core.Position{ + Line: arrBypassConn.GetStop().GetLine(), + Column: arrBypassConn.GetStop().GetColumn(), + }, + Location: s.loc, + } + + senderPortAddrParsed, err := s.parseSinglePortAddr( + "in", + senderPortAddr, + meta, + ) + if err != nil { + return src.Connection{}, err + } + + receiverPortAddrParsed, err := s.parseSinglePortAddr( + "out", + receiverPortAddr, + meta, + ) + if err != nil { + return src.Connection{}, err + } + + return src.Connection{ + ArrayBypass: &src.ArrayBypassConnection{ + SenderOutport: senderPortAddrParsed, + ReceiverInport: receiverPortAddrParsed, + }, + Meta: meta, + }, nil +} + +func (s *treeShapeListener) parseNormConn( + actx generated.INormConnDefContext, +) (src.Connection, *compiler.Error) { + meta := core.Meta{ + Text: actx.GetText(), + Start: core.Position{ + Line: actx.GetStart().GetLine(), + Column: actx.GetStart().GetColumn(), + }, + Stop: core.Position{ + Line: actx.GetStop().GetLine(), + Column: actx.GetStop().GetColumn(), + }, + Location: s.loc, + } + + parsedSenderSide, err := s.parseSenderSide(actx.SenderSide()) + if err != nil { + return src.Connection{}, err + } + + parsedReceiverSide, err := s.parseReceiverSide(actx.ReceiverSide()) + if err != nil { + return src.Connection{}, err + } + + return src.Connection{ + Normal: &src.NormalConnection{ + Senders: parsedSenderSide, + Receivers: parsedReceiverSide, + }, + Meta: meta, + }, nil +} + +func (s *treeShapeListener) parseSenderSide( + actx generated.ISenderSideContext, +) ([]src.ConnectionSender, *compiler.Error) { + singleSender := actx.SingleSenderSide() + mulSenders := actx.MultipleSenderSide() + + meta := core.Meta{ + Text: actx.GetText(), + Start: core.Position{ + Line: actx.GetStart().GetLine(), + Column: actx.GetStart().GetColumn(), + }, + Stop: core.Position{ + Line: actx.GetStop().GetLine(), + Column: actx.GetStop().GetColumn(), + }, + Location: s.loc, + } + + if singleSender == nil && mulSenders == nil { + return nil, &compiler.Error{ + Message: "Connection must have at least one sender side", + Meta: &meta, + } + } + + toParse := []generated.ISingleSenderSideContext{} + if singleSender != nil { + toParse = append(toParse, singleSender) + } else { + toParse = mulSenders.AllSingleSenderSide() + } + + parsedSenders := []src.ConnectionSender{} + for _, senderSide := range toParse { + parsedSide, err := s.parseSingleSender(senderSide) + if err != nil { + return nil, err + } + parsedSenders = append(parsedSenders, parsedSide) + } + + return parsedSenders, nil +} + +func (s *treeShapeListener) parseSingleReceiverSide( + actx generated.ISingleReceiverSideContext, +) (src.ConnectionReceiver, *compiler.Error) { + deferredConn := actx.DeferredConn() + portAddr := actx.PortAddr() + chainedConn := actx.ChainedNormConn() + switchStmt := actx.SwitchStmt() + + meta := core.Meta{ + Text: actx.GetText(), + Start: core.Position{ + Line: actx.GetStart().GetLine(), + Column: actx.GetStart().GetColumn(), + }, + Stop: core.Position{ + Line: actx.GetStop().GetLine(), + Column: actx.GetStop().GetColumn(), + }, + Location: s.loc, + } + + switch { + case deferredConn != nil: + return s.parseDeferredConn(deferredConn) + case chainedConn != nil: + return s.parseChainedConnExpr(chainedConn, meta) + case portAddr != nil: + return s.parsePortAddrReceiver(portAddr) + case switchStmt != nil: + return s.parseSwitchStmt(switchStmt) + default: + return src.ConnectionReceiver{}, &compiler.Error{ + Message: "missing receiver side", + Meta: &meta, + } + } +} + +func (s *treeShapeListener) parseSwitchStmt( + switchStmt generated.ISwitchStmtContext, +) (src.ConnectionReceiver, *compiler.Error) { + meta := core.Meta{ + Text: switchStmt.GetText(), + Start: core.Position{ + Line: switchStmt.GetStart().GetLine(), + Column: switchStmt.GetStart().GetColumn(), + }, + Stop: core.Position{ + Line: switchStmt.GetStop().GetLine(), + Column: switchStmt.GetStop().GetColumn(), + }, + Location: s.loc, + } + + unparsedCases := switchStmt.AllNormConnDef() + cases := make([]src.NormalConnection, 0, len(unparsedCases)) + for _, connDef := range unparsedCases { + parsedConn, err := s.parseNormConn(connDef) + if err != nil { + return src.ConnectionReceiver{}, err + } + cases = append(cases, *parsedConn.Normal) + } + + var defaultCase []src.ConnectionReceiver = nil + defaultCaseCtx := switchStmt.DefaultCase() + if defaultCaseCtx != nil { + parsedDefault, err := s.parseReceiverSide(defaultCaseCtx.ReceiverSide()) + if err != nil { + return src.ConnectionReceiver{}, err + } + defaultCase = parsedDefault + } + + return src.ConnectionReceiver{ + Switch: &src.Switch{ + Cases: cases, + Default: defaultCase, + }, + Meta: meta, + }, nil +} + +func (s *treeShapeListener) parseChainedConnExpr( + actx generated.IChainedNormConnContext, + connMeta core.Meta, +) (src.ConnectionReceiver, *compiler.Error) { + parsedConn, err := s.parseNormConn(actx.NormConnDef()) + if err != nil { + return src.ConnectionReceiver{}, err + } + + return src.ConnectionReceiver{ + ChainedConnection: &parsedConn, + Meta: connMeta, + }, nil +} + +func (s *treeShapeListener) parseReceiverSide( + actx generated.IReceiverSideContext, +) ([]src.ConnectionReceiver, *compiler.Error) { + singleReceiverSide := actx.SingleReceiverSide() + multipleReceiverSide := actx.MultipleReceiverSide() + + meta := core.Meta{ + Text: actx.GetText(), + Start: core.Position{ + Line: actx.GetStart().GetLine(), + Column: actx.GetStart().GetColumn(), + }, + Stop: core.Position{ + Line: actx.GetStop().GetLine(), + Column: actx.GetStop().GetColumn(), + }, + Location: s.loc, + } + + switch { + case singleReceiverSide != nil: + parsedSingleReceiver, err := s.parseSingleReceiverSide(singleReceiverSide) + if err != nil { + return nil, err + } + return []src.ConnectionReceiver{parsedSingleReceiver}, nil + case multipleReceiverSide != nil: + return s.parseMultipleReceiverSides(multipleReceiverSide) + default: + return nil, &compiler.Error{ + Message: "missing receiver side", + Meta: &meta, + } + } +} + +func (s *treeShapeListener) parseMultipleReceiverSides( + multipleSides generated.IMultipleReceiverSideContext, +) ( + []src.ConnectionReceiver, + *compiler.Error, +) { + allSingleReceiverSides := multipleSides.AllSingleReceiverSide() + parsedReceivers := make([]src.ConnectionReceiver, 0, len(allSingleReceiverSides)) + + for _, receiverSide := range allSingleReceiverSides { + parsedReceiver, err := s.parseSingleReceiverSide(receiverSide) + if err != nil { + return nil, err + } + parsedReceivers = append(parsedReceivers, parsedReceiver) + } + + return parsedReceivers, nil +} + +func (s *treeShapeListener) parseDeferredConn( + deferredConns generated.IDeferredConnContext, +) (src.ConnectionReceiver, *compiler.Error) { + meta := core.Meta{ + Text: deferredConns.GetText(), + Start: core.Position{ + Line: deferredConns.GetStart().GetLine(), + Column: deferredConns.GetStart().GetColumn(), + }, + Stop: core.Position{ + Line: deferredConns.GetStop().GetLine(), + Column: deferredConns.GetStop().GetColumn(), + }, + Location: s.loc, + } + + parsedConns, err := s.parseConnection(deferredConns.ConnDef()) + if err != nil { + return src.ConnectionReceiver{}, err + } + + return src.ConnectionReceiver{ + DeferredConnection: &parsedConns, + Meta: meta, + }, nil +} + +func (s *treeShapeListener) parseSingleSender( + senderSide generated.ISingleSenderSideContext, +) (src.ConnectionSender, *compiler.Error) { + structSelectors := senderSide.StructSelectors() + portSender := senderSide.PortAddr() + constRefSender := senderSide.SenderConstRef() + primitiveConstLitSender := senderSide.PrimitiveConstLit() + rangeExprSender := senderSide.RangeExpr() + ternaryExprSender := senderSide.TernaryExpr() + binaryExprSender := senderSide.BinaryExpr() + + if portSender == nil && + constRefSender == nil && + primitiveConstLitSender == nil && + rangeExprSender == nil && + structSelectors == nil && + ternaryExprSender == nil && + binaryExprSender == nil { + return src.ConnectionSender{}, &compiler.Error{ + Message: "Sender side is missing in connection", + Meta: &core.Meta{ + Text: senderSide.GetText(), + Start: core.Position{ + Line: senderSide.GetStart().GetLine(), + Column: senderSide.GetStart().GetColumn(), + }, + Stop: core.Position{ + Line: senderSide.GetStop().GetLine(), + Column: senderSide.GetStop().GetColumn(), + }, + Location: s.loc, + }, + } + } + + var senderSidePortAddr *src.PortAddr + if portSender != nil { + parsedPortAddr, err := s.parsePortAddr(portSender, "in") + if err != nil { + return src.ConnectionSender{}, err + } + senderSidePortAddr = &parsedPortAddr + } + + var constant *src.Const + if constRefSender != nil { + parsedEntityRef, err := s.parseEntityRef(constRefSender.EntityRef()) + if err != nil { + return src.ConnectionSender{}, err + } + constant = &src.Const{ + Value: src.ConstValue{ + Ref: &parsedEntityRef, + }, + } + } + + if primitiveConstLitSender != nil { + parsedPrimitiveConstLiteralSender, err := s.parsePrimitiveConstLiteral(primitiveConstLitSender) + if err != nil { + return src.ConnectionSender{}, err + } + constant = &parsedPrimitiveConstLiteralSender + } + + var rangeExpr *src.Range + if rangeExprSender != nil { + rangeMeta := &core.Meta{ + Text: rangeExprSender.GetText(), + Start: core.Position{ + Line: rangeExprSender.GetStart().GetLine(), + Column: rangeExprSender.GetStart().GetColumn(), + }, + Stop: core.Position{ + Line: rangeExprSender.GetStop().GetLine(), + Column: rangeExprSender.GetStop().GetColumn(), + }, + Location: s.loc, + } + + members := rangeExprSender.AllRangeMember() + if len(members) != 2 { + return src.ConnectionSender{}, &compiler.Error{ + Message: "Range expression must have exactly two members", + Meta: rangeMeta, + } + } + + fromCtx := members[0] + fromText := fromCtx.GetText() + + from, err := strconv.ParseInt(fromText, 10, 64) + if err != nil { + return src.ConnectionSender{}, &compiler.Error{ + Message: fmt.Sprintf("Invalid range 'from' value: %v", err), + Meta: &core.Meta{ + Text: rangeExprSender.GetText(), + Start: core.Position{ + Line: rangeExprSender.GetStart().GetLine(), + Column: rangeExprSender.GetStart().GetColumn(), + }, + Stop: core.Position{ + Line: rangeExprSender.GetStop().GetLine(), + Column: rangeExprSender.GetStop().GetColumn(), + }, + Location: s.loc, + }, + } + } + + toCtx := members[1] + toText := toCtx.GetText() + + to, err := strconv.ParseInt(toText, 10, 64) + if err != nil { + return src.ConnectionSender{}, &compiler.Error{ + Message: fmt.Sprintf("Invalid range 'to' value: %v", err), + Meta: &core.Meta{ + Text: rangeExprSender.GetText(), + Start: core.Position{ + Line: rangeExprSender.GetStart().GetLine(), + Column: rangeExprSender.GetStart().GetColumn(), + }, + Stop: core.Position{ + Line: rangeExprSender.GetStop().GetLine(), + Column: rangeExprSender.GetStop().GetColumn(), + }, + Location: s.loc, + }, + } + } + + rangeExpr = &src.Range{ + From: from, + To: to, + Meta: *rangeMeta, + } + } + + var senderSelectors []string + if structSelectors != nil { + for _, id := range structSelectors.AllIDENTIFIER() { + senderSelectors = append(senderSelectors, id.GetText()) + } + } + + var ternaryExpr *src.Ternary + if ternaryExprSender != nil { + parts := ternaryExprSender.AllSingleSenderSide() + + condition, err := s.parseSingleSender(parts[0]) + if err != nil { + return src.ConnectionSender{}, err + } + left, err := s.parseSingleSender(parts[1]) + if err != nil { + return src.ConnectionSender{}, err + } + right, err := s.parseSingleSender(parts[2]) + if err != nil { + return src.ConnectionSender{}, err + } + + ternaryExpr = &src.Ternary{ + Condition: condition, + Left: left, + Right: right, + Meta: core.Meta{ + Text: ternaryExprSender.GetText(), + Start: core.Position{ + Line: ternaryExprSender.GetStart().GetLine(), + Column: ternaryExprSender.GetStart().GetColumn(), + }, + Stop: core.Position{ + Line: ternaryExprSender.GetStop().GetLine(), + Column: ternaryExprSender.GetStop().GetColumn(), + }, + Location: s.loc, + }, + } + } + + var binaryExpr *src.Binary + if binaryExprSender != nil { + binaryExpr = s.parseBinaryExpr(binaryExprSender) + } + + parsedSender := src.ConnectionSender{ + PortAddr: senderSidePortAddr, + Const: constant, + Range: rangeExpr, + StructSelector: senderSelectors, + Ternary: ternaryExpr, + Binary: binaryExpr, + Meta: core.Meta{ + Text: senderSide.GetText(), + Start: core.Position{ + Line: senderSide.GetStart().GetLine(), + Column: senderSide.GetStart().GetColumn(), + }, + Stop: core.Position{ + Line: senderSide.GetStop().GetLine(), + Column: senderSide.GetStop().GetColumn(), + }, + Location: s.loc, + }, + } + + return parsedSender, nil +} + +func (s *treeShapeListener) parsePortAddrReceiver( + singleReceiver generated.IPortAddrContext, +) ( + src.ConnectionReceiver, + *compiler.Error, +) { + portAddr, err := s.parsePortAddr(singleReceiver, "out") + if err != nil { + return src.ConnectionReceiver{}, err + } + + return src.ConnectionReceiver{ + PortAddr: &portAddr, + Meta: core.Meta{ + Text: singleReceiver.GetText(), + Start: core.Position{ + Line: singleReceiver.GetStart().GetLine(), + Column: singleReceiver.GetStart().GetColumn(), + }, + Stop: core.Position{ + Line: singleReceiver.GetStop().GetLine(), + Column: singleReceiver.GetStop().GetColumn(), + }, + Location: s.loc, + }, + }, nil +} + +func (s *treeShapeListener) parseBinaryExpr(ctx generated.IBinaryExprContext) *src.Binary { + var op src.BinaryOperator + switch ctx.BinaryOp().GetText() { + // Arithmetic + case "+": + op = src.AddOp + case "-": + op = src.SubOp + case "*": + op = src.MulOp + case "/": + op = src.DivOp + case "%": + op = src.ModOp + case "**": + op = src.PowOp + // Comparison + case "==": + op = src.EqOp + case "!=": + op = src.NeOp + case ">": + op = src.GtOp + case "<": + op = src.LtOp + case ">=": + op = src.GeOp + case "<=": + op = src.LeOp + // Logical + case "&&": + op = src.AndOp + case "||": + op = src.OrOp + // Bitwise + case "&": + op = src.BitAndOp + case "|": + op = src.BitOrOp + case "^": + op = src.BitXorOp + case "<<": + op = src.BitLshOp + case ">>": + op = src.BitRshOp + } + + senders := ctx.AllSingleSenderSide() + + left, err := s.parseSingleSender(senders[0]) + if err != nil { + return nil + } + + right, err := s.parseSingleSender(senders[1]) + if err != nil { + return nil + } + + return &src.Binary{ + Left: left, + Right: right, + Operator: op, + Meta: core.Meta{ + Text: ctx.GetText(), + Start: core.Position{ + Line: ctx.GetStart().GetLine(), + Column: ctx.GetStart().GetColumn(), + }, + Stop: core.Position{ + Line: ctx.GetStop().GetLine(), + Column: ctx.GetStop().GetColumn(), + }, + Location: s.loc, + }, + } +} diff --git a/internal/compiler/parser/manifest.go b/internal/compiler/parser/manifest.go index af2437ad..8b0182ca 100644 --- a/internal/compiler/parser/manifest.go +++ b/internal/compiler/parser/manifest.go @@ -6,6 +6,7 @@ import ( yaml "gopkg.in/yaml.v3" src "github.com/nevalang/neva/internal/compiler/sourcecode" + "github.com/nevalang/neva/internal/compiler/sourcecode/core" ) func (p Parser) ParseManifest(raw []byte) (src.ModuleManifest, error) { @@ -17,14 +18,14 @@ func (p Parser) ParseManifest(raw []byte) (src.ModuleManifest, error) { } func processParsedManifest(manifest src.ModuleManifest) src.ModuleManifest { - deps := make(map[string]src.ModuleRef, len(manifest.Deps)) + deps := make(map[string]core.ModuleRef, len(manifest.Deps)) for alias, dep := range manifest.Deps { path := dep.Path if path == "" { path = alias } - deps[alias] = src.ModuleRef{ + deps[alias] = core.ModuleRef{ Path: path, Version: dep.Version, } diff --git a/internal/compiler/parser/network.go b/internal/compiler/parser/network.go deleted file mode 100644 index ff49adb5..00000000 --- a/internal/compiler/parser/network.go +++ /dev/null @@ -1,665 +0,0 @@ -package parser - -import ( - "fmt" - "strconv" - - "github.com/nevalang/neva/internal/compiler" - generated "github.com/nevalang/neva/internal/compiler/parser/generated" - src "github.com/nevalang/neva/internal/compiler/sourcecode" - "github.com/nevalang/neva/internal/compiler/sourcecode/core" -) - -func parseConnections(actx generated.IConnDefListContext) ([]src.Connection, *compiler.Error) { - allConnDefs := actx.AllConnDef() - parsedConns := make([]src.Connection, 0, len(allConnDefs)) - - for _, connDef := range allConnDefs { - parsedConnection, err := parseConnection(connDef) - if err != nil { - return nil, err - } - parsedConns = append(parsedConns, parsedConnection) - } - - return parsedConns, nil -} - -func parseConnection(connDef generated.IConnDefContext) (src.Connection, *compiler.Error) { - meta := core.Meta{ - Text: connDef.GetText(), - Start: core.Position{ - Line: connDef.GetStart().GetLine(), - Column: connDef.GetStart().GetColumn(), - }, - Stop: core.Position{ - Line: connDef.GetStop().GetLine(), - Column: connDef.GetStop().GetColumn(), - }, - } - - normConn := connDef.NormConnDef() - arrBypassConn := connDef.ArrBypassConnDef() - - if normConn == nil && arrBypassConn == nil { - return src.Connection{}, &compiler.Error{ - Message: "Connection must be either normal or array bypass", - Meta: &meta, - } - } - - if arrBypassConn != nil { - return parseArrayBypassConn(arrBypassConn) - } - - return parseNormConn(normConn) -} - -func parseArrayBypassConn( - arrBypassConn generated.IArrBypassConnDefContext, -) (src.Connection, *compiler.Error) { - senderPortAddr := arrBypassConn.SinglePortAddr(0) - receiverPortAddr := arrBypassConn.SinglePortAddr(1) - - meta := core.Meta{ - Text: arrBypassConn.GetText(), - Start: core.Position{ - Line: arrBypassConn.GetStart().GetLine(), - Column: arrBypassConn.GetStart().GetColumn(), - }, - Stop: core.Position{ - Line: arrBypassConn.GetStop().GetLine(), - Column: arrBypassConn.GetStop().GetColumn(), - }, - } - - senderPortAddrParsed, err := parseSinglePortAddr( - "in", - senderPortAddr, - meta, - ) - if err != nil { - return src.Connection{}, err - } - - receiverPortAddrParsed, err := parseSinglePortAddr( - "out", - receiverPortAddr, - meta, - ) - if err != nil { - return src.Connection{}, err - } - - return src.Connection{ - ArrayBypass: &src.ArrayBypassConnection{ - SenderOutport: senderPortAddrParsed, - ReceiverInport: receiverPortAddrParsed, - }, - Meta: meta, - }, nil -} - -func parseNormConn( - actx generated.INormConnDefContext, -) (src.Connection, *compiler.Error) { - meta := core.Meta{ - Text: actx.GetText(), - Start: core.Position{ - Line: actx.GetStart().GetLine(), - Column: actx.GetStart().GetColumn(), - }, - Stop: core.Position{ - Line: actx.GetStop().GetLine(), - Column: actx.GetStop().GetColumn(), - }, - } - - parsedSenderSide, err := parseSenderSide(actx.SenderSide()) - if err != nil { - return src.Connection{}, err - } - - parsedReceiverSide, err := parseReceiverSide(actx.ReceiverSide()) - if err != nil { - return src.Connection{}, err - } - - return src.Connection{ - Normal: &src.NormalConnection{ - Senders: parsedSenderSide, - Receivers: parsedReceiverSide, - }, - Meta: meta, - }, nil -} - -func parseSenderSide( - actx generated.ISenderSideContext, -) ([]src.ConnectionSender, *compiler.Error) { - singleSender := actx.SingleSenderSide() - mulSenders := actx.MultipleSenderSide() - - meta := core.Meta{ - Text: actx.GetText(), - Start: core.Position{ - Line: actx.GetStart().GetLine(), - Column: actx.GetStart().GetColumn(), - }, - Stop: core.Position{ - Line: actx.GetStop().GetLine(), - Column: actx.GetStop().GetColumn(), - }, - } - - if singleSender == nil && mulSenders == nil { - return nil, &compiler.Error{ - Message: "Connection must have at least one sender side", - Meta: &meta, - } - } - - toParse := []generated.ISingleSenderSideContext{} - if singleSender != nil { - toParse = append(toParse, singleSender) - } else { - toParse = mulSenders.AllSingleSenderSide() - } - - parsedSenders := []src.ConnectionSender{} - for _, senderSide := range toParse { - parsedSide, err := parseSingleSender(senderSide) - if err != nil { - return nil, err - } - parsedSenders = append(parsedSenders, parsedSide) - } - - return parsedSenders, nil -} - -func parseSingleReceiverSide( - actx generated.ISingleReceiverSideContext, -) (src.ConnectionReceiver, *compiler.Error) { - deferredConn := actx.DeferredConn() - portAddr := actx.PortAddr() - chainedConn := actx.ChainedNormConn() - switchStmt := actx.SwitchStmt() - - meta := core.Meta{ - Text: actx.GetText(), - Start: core.Position{ - Line: actx.GetStart().GetLine(), - Column: actx.GetStart().GetColumn(), - }, - Stop: core.Position{ - Line: actx.GetStop().GetLine(), - Column: actx.GetStop().GetColumn(), - }, - } - - switch { - case deferredConn != nil: - return parseDeferredConn(deferredConn) - case chainedConn != nil: - return parseChainedConnExpr(chainedConn, meta) - case portAddr != nil: - return parsePortAddrReceiver(portAddr) - case switchStmt != nil: - return parseSwitchStmt(switchStmt) - default: - return src.ConnectionReceiver{}, &compiler.Error{ - Message: "missing receiver side", - Meta: &meta, - } - } -} - -func parseSwitchStmt( - switchStmt generated.ISwitchStmtContext, -) (src.ConnectionReceiver, *compiler.Error) { - meta := core.Meta{ - Text: switchStmt.GetText(), - Start: core.Position{ - Line: switchStmt.GetStart().GetLine(), - Column: switchStmt.GetStart().GetColumn(), - }, - Stop: core.Position{ - Line: switchStmt.GetStop().GetLine(), - Column: switchStmt.GetStop().GetColumn(), - }, - } - - unparsedCases := switchStmt.AllNormConnDef() - cases := make([]src.NormalConnection, 0, len(unparsedCases)) - for _, connDef := range unparsedCases { - parsedConn, err := parseNormConn(connDef) - if err != nil { - return src.ConnectionReceiver{}, err - } - cases = append(cases, *parsedConn.Normal) - } - - var defaultCase []src.ConnectionReceiver = nil - defaultCaseCtx := switchStmt.DefaultCase() - if defaultCaseCtx != nil { - parsedDefault, err := parseReceiverSide(defaultCaseCtx.ReceiverSide()) - if err != nil { - return src.ConnectionReceiver{}, err - } - defaultCase = parsedDefault - } - - return src.ConnectionReceiver{ - Switch: &src.Switch{ - Cases: cases, - Default: defaultCase, - }, - Meta: meta, - }, nil -} - -func parseChainedConnExpr( - actx generated.IChainedNormConnContext, - connMeta core.Meta, -) (src.ConnectionReceiver, *compiler.Error) { - parsedConn, err := parseNormConn(actx.NormConnDef()) - if err != nil { - return src.ConnectionReceiver{}, err - } - - return src.ConnectionReceiver{ - ChainedConnection: &parsedConn, - Meta: connMeta, - }, nil -} - -func parseReceiverSide( - actx generated.IReceiverSideContext, -) ([]src.ConnectionReceiver, *compiler.Error) { - singleReceiverSide := actx.SingleReceiverSide() - multipleReceiverSide := actx.MultipleReceiverSide() - - meta := core.Meta{ - Text: actx.GetText(), - Start: core.Position{ - Line: actx.GetStart().GetLine(), - Column: actx.GetStart().GetColumn(), - }, - Stop: core.Position{ - Line: actx.GetStop().GetLine(), - Column: actx.GetStop().GetColumn(), - }, - } - - switch { - case singleReceiverSide != nil: - parsedSingleReceiver, err := parseSingleReceiverSide(singleReceiverSide) - if err != nil { - return nil, err - } - return []src.ConnectionReceiver{parsedSingleReceiver}, nil - case multipleReceiverSide != nil: - return parseMultipleReceiverSides(multipleReceiverSide) - default: - return nil, &compiler.Error{ - Message: "missing receiver side", - Meta: &meta, - } - } -} - -func parseMultipleReceiverSides( - multipleSides generated.IMultipleReceiverSideContext, -) ( - []src.ConnectionReceiver, - *compiler.Error, -) { - allSingleReceiverSides := multipleSides.AllSingleReceiverSide() - parsedReceivers := make([]src.ConnectionReceiver, 0, len(allSingleReceiverSides)) - - for _, receiverSide := range allSingleReceiverSides { - parsedReceiver, err := parseSingleReceiverSide(receiverSide) - if err != nil { - return nil, err - } - parsedReceivers = append(parsedReceivers, parsedReceiver) - } - - return parsedReceivers, nil -} - -func parseDeferredConn( - deferredConns generated.IDeferredConnContext, -) (src.ConnectionReceiver, *compiler.Error) { - meta := core.Meta{ - Text: deferredConns.GetText(), - Start: core.Position{ - Line: deferredConns.GetStart().GetLine(), - Column: deferredConns.GetStart().GetColumn(), - }, - Stop: core.Position{ - Line: deferredConns.GetStop().GetLine(), - Column: deferredConns.GetStop().GetColumn(), - }, - } - - parsedConns, err := parseConnection(deferredConns.ConnDef()) - if err != nil { - return src.ConnectionReceiver{}, err - } - - return src.ConnectionReceiver{ - DeferredConnection: &parsedConns, - Meta: meta, - }, nil -} - -func parseSingleSender( - senderSide generated.ISingleSenderSideContext, -) (src.ConnectionSender, *compiler.Error) { - structSelectors := senderSide.StructSelectors() - portSender := senderSide.PortAddr() - constRefSender := senderSide.SenderConstRef() - primitiveConstLitSender := senderSide.PrimitiveConstLit() - rangeExprSender := senderSide.RangeExpr() - ternaryExprSender := senderSide.TernaryExpr() - binaryExprSender := senderSide.BinaryExpr() - - if portSender == nil && - constRefSender == nil && - primitiveConstLitSender == nil && - rangeExprSender == nil && - structSelectors == nil && - ternaryExprSender == nil && - binaryExprSender == nil { - return src.ConnectionSender{}, &compiler.Error{ - Message: "Sender side is missing in connection", - Meta: &core.Meta{ - Text: senderSide.GetText(), - Start: core.Position{ - Line: senderSide.GetStart().GetLine(), - Column: senderSide.GetStart().GetColumn(), - }, - Stop: core.Position{ - Line: senderSide.GetStop().GetLine(), - Column: senderSide.GetStop().GetColumn(), - }, - }, - } - } - - var senderSidePortAddr *src.PortAddr - if portSender != nil { - parsedPortAddr, err := parsePortAddr(portSender, "in") - if err != nil { - return src.ConnectionSender{}, err - } - senderSidePortAddr = &parsedPortAddr - } - - var constant *src.Const - if constRefSender != nil { - parsedEntityRef, err := parseEntityRef(constRefSender.EntityRef()) - if err != nil { - return src.ConnectionSender{}, err - } - constant = &src.Const{ - Value: src.ConstValue{ - Ref: &parsedEntityRef, - }, - } - } - - if primitiveConstLitSender != nil { - parsedPrimitiveConstLiteralSender, err := parsePrimitiveConstLiteral(primitiveConstLitSender) - if err != nil { - return src.ConnectionSender{}, err - } - constant = &parsedPrimitiveConstLiteralSender - } - - var rangeExpr *src.Range - if rangeExprSender != nil { - rangeMeta := &core.Meta{ - Text: rangeExprSender.GetText(), - Start: core.Position{ - Line: rangeExprSender.GetStart().GetLine(), - Column: rangeExprSender.GetStart().GetColumn(), - }, - Stop: core.Position{ - Line: rangeExprSender.GetStop().GetLine(), - Column: rangeExprSender.GetStop().GetColumn(), - }, - } - - members := rangeExprSender.AllRangeMember() - if len(members) != 2 { - return src.ConnectionSender{}, &compiler.Error{ - Message: "Range expression must have exactly two members", - Meta: rangeMeta, - } - } - - fromCtx := members[0] - fromText := fromCtx.GetText() - - from, err := strconv.ParseInt(fromText, 10, 64) - if err != nil { - return src.ConnectionSender{}, &compiler.Error{ - Message: fmt.Sprintf("Invalid range 'from' value: %v", err), - Meta: &core.Meta{ - Text: rangeExprSender.GetText(), - Start: core.Position{ - Line: rangeExprSender.GetStart().GetLine(), - Column: rangeExprSender.GetStart().GetColumn(), - }, - Stop: core.Position{ - Line: rangeExprSender.GetStop().GetLine(), - Column: rangeExprSender.GetStop().GetColumn(), - }, - }, - } - } - - toCtx := members[1] - toText := toCtx.GetText() - - to, err := strconv.ParseInt(toText, 10, 64) - if err != nil { - return src.ConnectionSender{}, &compiler.Error{ - Message: fmt.Sprintf("Invalid range 'to' value: %v", err), - Meta: &core.Meta{ - Text: rangeExprSender.GetText(), - Start: core.Position{ - Line: rangeExprSender.GetStart().GetLine(), - Column: rangeExprSender.GetStart().GetColumn(), - }, - Stop: core.Position{ - Line: rangeExprSender.GetStop().GetLine(), - Column: rangeExprSender.GetStop().GetColumn(), - }, - }, - } - } - - rangeExpr = &src.Range{ - From: from, - To: to, - Meta: *rangeMeta, - } - } - - var senderSelectors []string - if structSelectors != nil { - for _, id := range structSelectors.AllIDENTIFIER() { - senderSelectors = append(senderSelectors, id.GetText()) - } - } - - var ternaryExpr *src.Ternary - if ternaryExprSender != nil { - parts := ternaryExprSender.AllSingleSenderSide() - - condition, err := parseSingleSender(parts[0]) - if err != nil { - return src.ConnectionSender{}, err - } - left, err := parseSingleSender(parts[1]) - if err != nil { - return src.ConnectionSender{}, err - } - right, err := parseSingleSender(parts[2]) - if err != nil { - return src.ConnectionSender{}, err - } - - ternaryExpr = &src.Ternary{ - Condition: condition, - Left: left, - Right: right, - Meta: core.Meta{ - Text: ternaryExprSender.GetText(), - Start: core.Position{ - Line: ternaryExprSender.GetStart().GetLine(), - Column: ternaryExprSender.GetStart().GetColumn(), - }, - Stop: core.Position{ - Line: ternaryExprSender.GetStop().GetLine(), - Column: ternaryExprSender.GetStop().GetColumn(), - }, - }, - } - } - - var binaryExpr *src.Binary - if binaryExprSender != nil { - binaryExpr = parseBinaryExpr(binaryExprSender) - } - - parsedSender := src.ConnectionSender{ - PortAddr: senderSidePortAddr, - Const: constant, - Range: rangeExpr, - StructSelector: senderSelectors, - Ternary: ternaryExpr, - Binary: binaryExpr, - Meta: core.Meta{ - Text: senderSide.GetText(), - Start: core.Position{ - Line: senderSide.GetStart().GetLine(), - Column: senderSide.GetStart().GetColumn(), - }, - Stop: core.Position{ - Line: senderSide.GetStop().GetLine(), - Column: senderSide.GetStop().GetColumn(), - }, - }, - } - - return parsedSender, nil -} - -func parsePortAddrReceiver( - singleReceiver generated.IPortAddrContext, -) ( - src.ConnectionReceiver, - *compiler.Error, -) { - portAddr, err := parsePortAddr(singleReceiver, "out") - if err != nil { - return src.ConnectionReceiver{}, err - } - - return src.ConnectionReceiver{ - PortAddr: &portAddr, - Meta: core.Meta{ - Text: singleReceiver.GetText(), - Start: core.Position{ - Line: singleReceiver.GetStart().GetLine(), - Column: singleReceiver.GetStart().GetColumn(), - }, - Stop: core.Position{ - Line: singleReceiver.GetStop().GetLine(), - Column: singleReceiver.GetStop().GetColumn(), - }, - }, - }, nil -} - -func parseBinaryExpr(ctx generated.IBinaryExprContext) *src.Binary { - var op src.BinaryOperator - switch ctx.BinaryOp().GetText() { - // Arithmetic - case "+": - op = src.AddOp - case "-": - op = src.SubOp - case "*": - op = src.MulOp - case "/": - op = src.DivOp - case "%": - op = src.ModOp - case "**": - op = src.PowOp - // Comparison - case "==": - op = src.EqOp - case "!=": - op = src.NeOp - case ">": - op = src.GtOp - case "<": - op = src.LtOp - case ">=": - op = src.GeOp - case "<=": - op = src.LeOp - // Logical - case "&&": - op = src.AndOp - case "||": - op = src.OrOp - // Bitwise - case "&": - op = src.BitAndOp - case "|": - op = src.BitOrOp - case "^": - op = src.BitXorOp - case "<<": - op = src.BitLshOp - case ">>": - op = src.BitRshOp - } - - senders := ctx.AllSingleSenderSide() - - left, err := parseSingleSender(senders[0]) - if err != nil { - return nil - } - - right, err := parseSingleSender(senders[1]) - if err != nil { - return nil - } - - return &src.Binary{ - Left: left, - Right: right, - Operator: op, - Meta: core.Meta{ - Text: ctx.GetText(), - Start: core.Position{ - Line: ctx.GetStart().GetLine(), - Column: ctx.GetStart().GetColumn(), - }, - Stop: core.Position{ - Line: ctx.GetStop().GetLine(), - Column: ctx.GetStop().GetColumn(), - }, - }, - } -} diff --git a/internal/compiler/parser/neva.g4 b/internal/compiler/parser/neva.g4 index f05afe40..9e1b9924 100644 --- a/internal/compiler/parser/neva.g4 +++ b/internal/compiler/parser/neva.g4 @@ -69,7 +69,7 @@ outPortsDef: portsDef; portsDef: '(' (NEWLINE* | portDef? | portDef (',' portDef)*) ')'; portDef: singlePortDef | arrayPortDef; -singlePortDef: NEWLINE* IDENTIFIER typeExpr? NEWLINE*; +singlePortDef: NEWLINE* IDENTIFIER? typeExpr NEWLINE*; arrayPortDef: NEWLINE* '[' IDENTIFIER ']' typeExpr? NEWLINE*; // const diff --git a/internal/compiler/parser/parser.go b/internal/compiler/parser/parser.go index 168d0eae..9d59543e 100644 --- a/internal/compiler/parser/parser.go +++ b/internal/compiler/parser/parser.go @@ -11,19 +11,15 @@ import ( "github.com/nevalang/neva/internal/compiler" generated "github.com/nevalang/neva/internal/compiler/parser/generated" src "github.com/nevalang/neva/internal/compiler/sourcecode" + "github.com/nevalang/neva/internal/compiler/sourcecode/core" ) -type treeShapeListener struct { - *generated.BasenevaListener - file src.File -} - type Parser struct{} func (p Parser) ParseModules( - rawMods map[src.ModuleRef]compiler.RawModule, -) (map[src.ModuleRef]src.Module, *compiler.Error) { - parsedMods := make(map[src.ModuleRef]src.Module, len(rawMods)) + rawMods map[core.ModuleRef]compiler.RawModule, +) (map[core.ModuleRef]src.Module, *compiler.Error) { + parsedMods := make(map[core.ModuleRef]src.Module, len(rawMods)) for modRef, rawMod := range rawMods { parsedPkgs, err := p.ParsePackages(modRef, rawMod.Packages) @@ -41,7 +37,7 @@ func (p Parser) ParseModules( } func (p Parser) ParsePackages( - modRef src.ModuleRef, + modRef core.ModuleRef, rawPkgs map[string]compiler.RawPackage, ) ( map[string]src.Package, @@ -61,20 +57,20 @@ func (p Parser) ParsePackages( } func (p Parser) ParseFiles( - modRef src.ModuleRef, + modRef core.ModuleRef, pkgName string, files map[string][]byte, ) (map[string]src.File, *compiler.Error) { result := make(map[string]src.File, len(files)) for fileName, fileBytes := range files { - parsedFile, err := p.parseFile(fileBytes) + parsedFile, err := p.parseFile(modRef, pkgName, fileName, fileBytes) if err != nil { - err.Location = compiler.Pointer(src.Location{ - Module: modRef, + err.Meta.Location = core.Location{ + ModRef: modRef, Package: pkgName, Filename: fileName, - }) + } return nil, err } result[fileName] = parsedFile @@ -83,8 +79,13 @@ func (p Parser) ParseFiles( return result, nil } -func (p Parser) parseFile(bb []byte) (src.File, *compiler.Error) { - input := antlr.NewInputStream(string(bb)) +func (p Parser) parseFile( + modRef core.ModuleRef, + pkgName string, + fileName string, + content []byte, +) (src.File, *compiler.Error) { + input := antlr.NewInputStream(string(content)) lexer := generated.NewnevaLexer(input) lexerErrors := &CustomErrorListener{} lexer.RemoveErrorListeners() @@ -97,7 +98,13 @@ func (p Parser) parseFile(bb []byte) (src.File, *compiler.Error) { prsr.AddErrorListener(parserErrors) prsr.BuildParseTrees = true - listener := &treeShapeListener{} + listener := &treeShapeListener{ + loc: core.Location{ + ModRef: modRef, + Package: pkgName, + Filename: fileName, + }, + } if err := walkTree(listener, prsr.Prog()); err != nil { return src.File{}, err @@ -111,7 +118,7 @@ func (p Parser) parseFile(bb []byte) (src.File, *compiler.Error) { return src.File{}, parserErrors.Errors[0] } - return listener.file, nil + return listener.state, nil } func walkTree(listener antlr.ParseTreeListener, tree antlr.ParseTree) (err *compiler.Error) { diff --git a/internal/compiler/parser/parser_test.go b/internal/compiler/parser/parser_test.go index 4000e7bc..8dd34afa 100644 --- a/internal/compiler/parser/parser_test.go +++ b/internal/compiler/parser/parser_test.go @@ -5,9 +5,19 @@ import ( "github.com/nevalang/neva/internal/compiler" src "github.com/nevalang/neva/internal/compiler/sourcecode" + "github.com/nevalang/neva/internal/compiler/sourcecode/core" "github.com/stretchr/testify/require" ) +var location = core.Location{ + ModRef: core.ModuleRef{ + Path: "test", + Version: "1", + }, + Package: "test", + Filename: "test", +} + func TestParser_ParseFile_TernaryExpression(t *testing.T) { text := []byte(` def C1() () { @@ -17,7 +27,7 @@ func TestParser_ParseFile_TernaryExpression(t *testing.T) { p := New() - got, err := p.parseFile(text) + got, err := p.parseFile(location.ModRef, location.Package, location.Filename, text) require.Nil(t, err) net := got.Entities["C1"].Component.Net @@ -45,7 +55,7 @@ func TestParser_ParseFile_NestedTernaryExpression(t *testing.T) { p := New() - got, err := p.parseFile(text) + got, err := p.parseFile(location.ModRef, location.Package, location.Filename, text) require.Nil(t, err) net := got.Entities["C1"].Component.Net @@ -76,7 +86,7 @@ func TestParser_ParseFile_StructSelectorsWithLonelyChain(t *testing.T) { }`, ) p := New() - got, err := p.parseFile(text) + got, err := p.parseFile(location.ModRef, location.Package, location.Filename, text) require.True(t, err == nil) net := got.Entities["C1"].Component.Net @@ -107,7 +117,7 @@ func TestParser_ParseFile_PortlessArrPortAddr(t *testing.T) { p := New() - got, err := p.parseFile(text) + got, err := p.parseFile(location.ModRef, location.Package, location.Filename, text) require.Equal(t, true, err == nil) net := got.Entities["C1"].Component.Net @@ -133,7 +143,7 @@ func TestParser_ParseFile_ChainedConnectionsWithDefer(t *testing.T) { p := New() - got, err := p.parseFile(text) + got, err := p.parseFile(location.ModRef, location.Package, location.Filename, text) require.True(t, err == nil) net := got.Entities["C1"].Component.Net @@ -168,7 +178,7 @@ func TestParser_ParseFile_LonelyPorts(t *testing.T) { p := New() - got, err := p.parseFile(text) + got, err := p.parseFile(location.ModRef, location.Package, location.Filename, text) require.True(t, err == nil) // 1) :port -> lonely @@ -194,7 +204,7 @@ func TestParser_ParseFile_ChainedConnections(t *testing.T) { p := New() - got, err := p.parseFile(text) + got, err := p.parseFile(location.ModRef, location.Package, location.Filename, text) require.True(t, err == nil) net := got.Entities["C1"].Component.Net @@ -266,7 +276,7 @@ func TestParser_ParseFile_ChainedConnectionsWithConstants(t *testing.T) { t.Run(tt.name, func(t *testing.T) { p := New() - got, err := p.parseFile([]byte(tt.text)) + got, err := p.parseFile(location.ModRef, location.Package, location.Filename, []byte(tt.text)) require.Nil(t, err) net := got.Entities["C1"].Component.Net @@ -282,7 +292,7 @@ func TestParser_ParseFile_Comments(t *testing.T) { p := New() - _, err := p.parseFile(text) + _, err := p.parseFile(location.ModRef, location.Package, location.Filename, text) require.True(t, err == nil) } @@ -311,7 +321,7 @@ func TestParser_ParseFile_Directives(t *testing.T) { p := New() - got, err := p.parseFile(text) + got, err := p.parseFile(location.ModRef, location.Package, location.Filename, text) require.True(t, err == nil) d1 := got.Entities["C1"].Component.Directives[compiler.ExternDirective][0] @@ -349,7 +359,7 @@ func TestParser_ParseFile_IONodes(t *testing.T) { p := New() - got, err := p.parseFile(text) + got, err := p.parseFile(location.ModRef, location.Package, location.Filename, text) require.True(t, err == nil) conn := got.Entities["C1"].Component.Net[0] @@ -372,7 +382,7 @@ func TestParser_ParseFile_AnonymousNodes(t *testing.T) { p := New() - got, err := p.parseFile(text) + got, err := p.parseFile(location.ModRef, location.Package, location.Filename, text) require.True(t, err == nil) nodes := got.Entities["C1"].Component.Nodes @@ -392,7 +402,7 @@ func TestParser_ParseFile_EnumLiterals(t *testing.T) { p := New() - got, err := p.parseFile(text) + got, err := p.parseFile(location.ModRef, location.Package, location.Filename, text) require.True(t, err == nil) enum := got.Entities["c0"].Const.Value.Message.Enum @@ -416,7 +426,7 @@ func TestParser_ParseFile_EnumLiteralSenders(t *testing.T) { p := New() - got, err := p.parseFile(text) + got, err := p.parseFile(location.ModRef, location.Package, location.Filename, text) require.True(t, err == nil) conn := got.Entities["C1"].Component.Net[0] @@ -548,7 +558,7 @@ func TestParser_ParseFile_Range(t *testing.T) { t.Run(tt.name, func(t *testing.T) { p := New() - got, err := p.parseFile([]byte(tt.text)) + got, err := p.parseFile(location.ModRef, location.Package, location.Filename, []byte(tt.text)) require.Nil(t, err) net := got.Entities["C1"].Component.Net @@ -679,7 +689,7 @@ func TestParser_ParseFile_Binary(t *testing.T) { t.Run(tt.name, func(t *testing.T) { p := New() - got, err := p.parseFile([]byte(tt.text)) + got, err := p.parseFile(location.ModRef, location.Package, location.Filename, []byte(tt.text)) require.Nil(t, err) net := got.Entities["C1"].Component.Net @@ -802,7 +812,7 @@ func TestParser_ParseFile_ComplexBinaryAndTernary(t *testing.T) { t.Run(tt.name, func(t *testing.T) { p := New() - got, err := p.parseFile([]byte(tt.text)) + got, err := p.parseFile(location.ModRef, location.Package, location.Filename, []byte(tt.text)) require.Nil(t, err) net := got.Entities["C1"].Component.Net @@ -994,7 +1004,7 @@ func TestParser_ParseFile_Switch(t *testing.T) { t.Run(tt.name, func(t *testing.T) { p := New() - got, err := p.parseFile([]byte(tt.text)) + got, err := p.parseFile(location.ModRef, location.Package, location.Filename, []byte(tt.text)) require.Nil(t, err) net := got.Entities["C1"].Component.Net From 0d1d1f93f50b0f1b325361ea2216b1462da99a20 Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Sat, 7 Dec 2024 04:55:06 +0500 Subject: [PATCH 12/28] feat(analyzer:error_handling): fill location from entity instead of scope and put it inside meta --- internal/compiler/analyzer/analyzer.go | 86 ++--- internal/compiler/analyzer/component.go | 25 +- internal/compiler/analyzer/const.go | 86 ++--- internal/compiler/analyzer/interface.go | 32 +- internal/compiler/analyzer/main_component.go | 22 +- internal/compiler/analyzer/main_pkg.go | 32 +- internal/compiler/analyzer/network.go | 333 +++++++------------ internal/compiler/analyzer/nodes.go | 105 +++--- internal/compiler/analyzer/semver.go | 3 +- internal/compiler/analyzer/type.go | 25 +- 10 files changed, 310 insertions(+), 439 deletions(-) diff --git a/internal/compiler/analyzer/analyzer.go b/internal/compiler/analyzer/analyzer.go index 6bd46676..4ce58410 100644 --- a/internal/compiler/analyzer/analyzer.go +++ b/internal/compiler/analyzer/analyzer.go @@ -24,42 +24,44 @@ type Analyzer struct { } func (a Analyzer) AnalyzeExecutableBuild(build src.Build, mainPkgName string) (src.Build, *compiler.Error) { - location := src.Location{ - Module: build.EntryModRef, - Package: mainPkgName, + meta := core.Meta{ + Location: core.Location{ + ModRef: build.EntryModRef, + Package: mainPkgName, + }, } entryMod, ok := build.Modules[build.EntryModRef] if !ok { return src.Build{}, &compiler.Error{ - Message: fmt.Sprintf("entry module not found: %s", build.EntryModRef), - Location: &location, + Message: fmt.Sprintf("entry module not found: %s", build.EntryModRef), + Meta: &meta, } } if _, ok := entryMod.Packages[mainPkgName]; !ok { return src.Build{}, &compiler.Error{ - Message: "main package not found", - Location: &location, + Message: "main package not found", + Meta: &meta, } } - scope := src.NewScope(build, location) + scope := src.NewScope(build, meta.Location) if err := a.mainSpecificPkgValidation(mainPkgName, entryMod, scope); err != nil { - return src.Build{}, compiler.Error{Location: &location}.Wrap(err) + return src.Build{}, compiler.Error{Meta: &meta}.Wrap(err) } analyzedBuild, err := a.AnalyzeBuild(build) if err != nil { - return src.Build{}, compiler.Error{Location: &location}.Wrap(err) + return src.Build{}, compiler.Error{Meta: &meta}.Wrap(err) } return analyzedBuild, nil } func (a Analyzer) AnalyzeBuild(build src.Build) (src.Build, *compiler.Error) { - analyzedMods := make(map[src.ModuleRef]src.Module, len(build.Modules)) + analyzedMods := make(map[core.ModuleRef]src.Module, len(build.Modules)) for modRef, mod := range build.Modules { if err := a.semverCheck(mod, modRef); err != nil { @@ -83,21 +85,27 @@ func (a Analyzer) AnalyzeBuild(build src.Build) (src.Build, *compiler.Error) { }, nil } -func (a Analyzer) analyzeModule(modRef src.ModuleRef, build src.Build) (map[string]src.Package, *compiler.Error) { +func (a Analyzer) analyzeModule(modRef core.ModuleRef, build src.Build) (map[string]src.Package, *compiler.Error) { if modRef != build.EntryModRef && modRef.Version == "" { return nil, &compiler.Error{ - Message: "every dependency module must have version", - Location: &src.Location{Module: modRef}, + Message: "every dependency module must have version", + Meta: &core.Meta{ + Location: core.Location{ + ModRef: modRef, + }, + }, } } - location := src.Location{Module: modRef} + location := core.Location{ModRef: modRef} mod := build.Modules[modRef] if len(mod.Packages) == 0 { return nil, &compiler.Error{ - Message: "module must contain at least one package", - Location: &location, + Message: "module must contain at least one package", + Meta: &core.Meta{ + Location: location, + }, } } @@ -105,16 +113,18 @@ func (a Analyzer) analyzeModule(modRef src.ModuleRef, build src.Build) (map[stri maps.Copy(pkgsCopy, mod.Packages) for pkgName, pkg := range pkgsCopy { - scope := src.NewScope(build, src.Location{ - Module: modRef, + scope := src.NewScope(build, core.Location{ + ModRef: modRef, Package: pkgName, }) resolvedPkg, err := a.analyzePkg(pkg, scope) if err != nil { return nil, compiler.Error{ - Location: &src.Location{ - Package: pkgName, + Meta: &core.Meta{ + Location: core.Location{ + Package: pkgName, + }, }, }.Wrap(err) } @@ -128,8 +138,10 @@ func (a Analyzer) analyzeModule(modRef src.ModuleRef, build src.Build) (map[stri func (a Analyzer) analyzePkg(pkg src.Package, scope src.Scope) (src.Package, *compiler.Error) { if len(pkg) == 0 { return nil, &compiler.Error{ - Message: "package must contain at least one file", - Location: scope.Location(), + Message: "package must contain at least one file", + Meta: &core.Meta{ + Location: *scope.Location(), + }, } } @@ -143,8 +155,8 @@ func (a Analyzer) analyzePkg(pkg src.Package, scope src.Scope) (src.Package, *co } for result := range pkg.Entities() { - relocatedScope := scope.Relocate(src.Location{ - Module: scope.Location().Module, + relocatedScope := scope.Relocate(core.Location{ + ModRef: scope.Location().ModRef, Package: scope.Location().Package, Filename: result.FileName, }) @@ -152,8 +164,7 @@ func (a Analyzer) analyzePkg(pkg src.Package, scope src.Scope) (src.Package, *co analyzedEntity, err := a.analyzeEntity(result.Entity, relocatedScope) if err != nil { return nil, compiler.Error{ - Location: relocatedScope.Location(), - Meta: result.Entity.Meta(), + Meta: result.Entity.Meta(), }.Wrap(err) } @@ -169,16 +180,15 @@ func (a Analyzer) analyzeEntity(entity src.Entity, scope src.Scope) (src.Entity, Kind: entity.Kind, } - isStd := scope.Location().Module.Path == "std" + isStd := scope.Location().ModRef.Path == "std" switch entity.Kind { case src.TypeEntity: resolvedTypeDef, err := a.analyzeTypeDef(entity.Type, scope, analyzeTypeDefParams{allowEmptyBody: isStd}) if err != nil { - meta := entity.Type.Meta.(core.Meta) //nolint:forcetypeassert + meta := entity.Type.Meta return src.Entity{}, compiler.Error{ - Location: scope.Location(), - Meta: &meta, + Meta: &meta, }.Wrap(err) } resolvedEntity.Type = resolvedTypeDef @@ -187,8 +197,7 @@ func (a Analyzer) analyzeEntity(entity src.Entity, scope src.Scope) (src.Entity, if err != nil { meta := entity.Const.Meta return src.Entity{}, compiler.Error{ - Location: scope.Location(), - Meta: &meta, + Meta: &meta, }.Wrap(err) } resolvedEntity.Const = resolvedConst @@ -200,8 +209,7 @@ func (a Analyzer) analyzeEntity(entity src.Entity, scope src.Scope) (src.Entity, if err != nil { meta := entity.Interface.Meta return src.Entity{}, compiler.Error{ - Location: scope.Location(), - Meta: &meta, + Meta: &meta, }.Wrap(err) } resolvedEntity.Interface = resolvedInterface @@ -209,16 +217,14 @@ func (a Analyzer) analyzeEntity(entity src.Entity, scope src.Scope) (src.Entity, analyzedComponent, err := a.analyzeComponent(entity.Component, scope) if err != nil { return src.Entity{}, compiler.Error{ - Location: scope.Location(), - Meta: &entity.Component.Meta, + Meta: &entity.Component.Meta, }.Wrap(err) } resolvedEntity.Component = analyzedComponent default: return src.Entity{}, &compiler.Error{ - Message: fmt.Sprintf("unknown entity kind: %v", entity.Kind), - Location: scope.Location(), - Meta: entity.Meta(), + Message: fmt.Sprintf("unknown entity kind: %v", entity.Kind), + Meta: entity.Meta(), } } diff --git a/internal/compiler/analyzer/component.go b/internal/compiler/analyzer/component.go index 22708e4a..d6b5d509 100644 --- a/internal/compiler/analyzer/component.go +++ b/internal/compiler/analyzer/component.go @@ -15,9 +15,8 @@ func (a Analyzer) analyzeComponent( if isRuntimeFunc && len(runtimeFuncArgs) == 0 { return src.Component{}, &compiler.Error{ - Message: "Component that use #extern directive must provide at least one argument", - Location: scope.Location(), - Meta: &component.Meta, + Message: "Component that use #extern directive must provide at least one argument", + Meta: &component.Meta, } } @@ -26,9 +25,8 @@ func (a Analyzer) analyzeComponent( parts := strings.Split(runtimeFuncArg, " ") if len(parts) != 2 { return src.Component{}, &compiler.Error{ - Message: "Component that use #extern with more than one argument must provide arguments in a form of pairs", - Location: scope.Location(), - Meta: &component.Meta, + Message: "Component that use #extern with more than one argument must provide arguments in a form of pairs", + Meta: &component.Meta, } } } @@ -44,8 +42,7 @@ func (a Analyzer) analyzeComponent( ) if err != nil { return src.Component{}, compiler.Error{ - Location: scope.Location(), - Meta: &component.Meta, + Meta: &component.Meta, }.Wrap(err) } @@ -53,8 +50,7 @@ func (a Analyzer) analyzeComponent( if len(component.Nodes) != 0 || len(component.Net) != 0 { return src.Component{}, &compiler.Error{ Message: "Component with nodes or network cannot use #extern directive", - Location: scope.Location(), - Meta: &component.Meta, + Meta: &component.Meta, } } return component, nil @@ -67,16 +63,14 @@ func (a Analyzer) analyzeComponent( ) if err != nil { return src.Component{}, compiler.Error{ - Location: scope.Location(), - Meta: &component.Meta, + Meta: &component.Meta, }.Wrap(err) } if len(component.Net) == 0 { return src.Component{}, &compiler.Error{ Message: "Component must have network", - Location: scope.Location(), - Meta: &component.Meta, + Meta: &component.Meta, } } @@ -90,8 +84,7 @@ func (a Analyzer) analyzeComponent( ) if err != nil { return src.Component{}, compiler.Error{ - Location: scope.Location(), - Meta: &component.Meta, + Meta: &component.Meta, }.Wrap(err) } diff --git a/internal/compiler/analyzer/const.go b/internal/compiler/analyzer/const.go index 12cfe40f..a51d34a6 100644 --- a/internal/compiler/analyzer/const.go +++ b/internal/compiler/analyzer/const.go @@ -18,27 +18,24 @@ func (a Analyzer) analyzeConst( ) (src.Const, *compiler.Error) { if constant.Value.Message == nil && constant.Value.Ref == nil { return src.Const{}, &compiler.Error{ - Message: "Constant must either have value or reference to another constant", - Location: scope.Location(), - Meta: &constant.Meta, + Message: "Constant must either have value or reference to another constant", + Meta: &constant.Meta, } } if constant.Value.Message == nil { // is ref - entity, location, err := scope.Entity(*constant.Value.Ref) + entity, _, err := scope.Entity(*constant.Value.Ref) if err != nil { return src.Const{}, &compiler.Error{ - Message: err.Error(), - Location: &location, - Meta: entity.Meta(), + Message: err.Error(), + Meta: entity.Meta(), } } if entity.Kind != src.ConstEntity { return src.Const{}, &compiler.Error{ - Message: fmt.Sprintf("Constant refers to an entity that is not constant: %v", entity.Kind), - Location: &location, - Meta: entity.Meta(), + Message: fmt.Sprintf("Constant refers to an entity that is not constant: %v", entity.Kind), + Meta: entity.Meta(), } } @@ -48,17 +45,15 @@ func (a Analyzer) analyzeConst( resolvedType, err := a.analyzeTypeExpr(constant.TypeExpr, scope) if err != nil { return src.Const{}, compiler.Error{ - Message: "Cannot resolve constant type", - Location: scope.Location(), - Meta: &constant.Meta, + Message: "Cannot resolve constant type", + Meta: &constant.Meta, }.Wrap(err) } if resolvedType.Lit != nil && resolvedType.Lit.Union != nil { return src.Const{}, &compiler.Error{ - Message: "Constant cannot have type union", - Location: scope.Location(), - Meta: &constant.Meta, + Message: "Constant cannot have type union", + Meta: &constant.Meta, } } @@ -77,9 +72,8 @@ func (a Analyzer) analyzeConst( case "bool": if constant.Value.Message.Bool == nil { return src.Const{}, &compiler.Error{ - Message: fmt.Sprintf("Boolean value is missing in boolean contant: %v", constant), - Location: scope.Location(), - Meta: &constant.Meta, + Message: fmt.Sprintf("Boolean value is missing in boolean contant: %v", constant), + Meta: &constant.Meta, } } if constant.Value.Message.Int != nil || @@ -93,16 +87,14 @@ func (a Analyzer) analyzeConst( "Constant cannot have several values at once: %v", constant, ), - Location: scope.Location(), - Meta: &constant.Meta, + Meta: &constant.Meta, } } case "int": if constant.Value.Message.Int == nil { return src.Const{}, &compiler.Error{ - Message: fmt.Sprintf("Integer value is missing in integer contant: %v", constant), - Location: scope.Location(), - Meta: &constant.Meta, + Message: fmt.Sprintf("Integer value is missing in integer contant: %v", constant), + Meta: &constant.Meta, } } if constant.Value.Message.Bool != nil || @@ -116,8 +108,7 @@ func (a Analyzer) analyzeConst( "Constant cannot have several values at once: %v", constant.Value.Message, ), - Location: scope.Location(), - Meta: &constant.Meta, + Meta: &constant.Meta, } } case "float": @@ -125,9 +116,8 @@ func (a Analyzer) analyzeConst( // We must pass this case. Desugarer will turn integer literal into float. if constant.Value.Message.Float == nil && constant.Value.Message.Int == nil { return src.Const{}, &compiler.Error{ - Message: fmt.Sprintf("Float or integer value is missing in float contant: %v", constant), - Location: scope.Location(), - Meta: &constant.Meta, + Message: fmt.Sprintf("Float or integer value is missing in float contant: %v", constant), + Meta: &constant.Meta, } } if constant.Value.Message.Float != nil && constant.Value.Message.Int != nil { @@ -136,8 +126,7 @@ func (a Analyzer) analyzeConst( "Constant cannot have several values at once: %v", constant.Value.Message, ), - Location: scope.Location(), - Meta: &constant.Meta, + Meta: &constant.Meta, } } if constant.Value.Message.Bool != nil || @@ -150,16 +139,14 @@ func (a Analyzer) analyzeConst( "Constant cannot have several values at once: %v", constant.Value.Message, ), - Location: scope.Location(), - Meta: &constant.Meta, + Meta: &constant.Meta, } } case "string": if constant.Value.Message.Str == nil { return src.Const{}, &compiler.Error{ - Message: fmt.Sprintf("String value is missing in string contant: %v", constant), - Location: scope.Location(), - Meta: &constant.Meta, + Message: fmt.Sprintf("String value is missing in string contant: %v", constant), + Meta: &constant.Meta, } } if constant.Value.Message.Bool != nil || @@ -173,16 +160,14 @@ func (a Analyzer) analyzeConst( "Constant cannot have several values at once: %v", constant.Value.Message, ), - Location: scope.Location(), - Meta: &constant.Meta, + Meta: &constant.Meta, } } case "list": if constant.Value.Message.List == nil { return src.Const{}, &compiler.Error{ - Message: fmt.Sprintf("List value is missing in list contant: %v", constant), - Location: scope.Location(), - Meta: &constant.Meta, + Message: fmt.Sprintf("List value is missing in list contant: %v", constant), + Meta: &constant.Meta, } } if constant.Value.Message.Bool != nil || @@ -195,16 +180,14 @@ func (a Analyzer) analyzeConst( "Constant cannot have several values at once: %v", constant.Value.Message, ), - Location: scope.Location(), - Meta: &constant.Meta, + Meta: &constant.Meta, } } case "map", "struct": if constant.Value.Message.DictOrStruct == nil { return src.Const{}, &compiler.Error{ - Message: fmt.Sprintf("Map or struct value is missing in map or struct contant: %v", constant), - Location: scope.Location(), - Meta: &constant.Meta, + Message: fmt.Sprintf("Map or struct value is missing in map or struct contant: %v", constant), + Meta: &constant.Meta, } } if constant.Value.Message.Bool != nil || @@ -217,16 +200,14 @@ func (a Analyzer) analyzeConst( "Constant cannot have several values at once: %v", constant.Value.Message, ), - Location: scope.Location(), - Meta: &constant.Meta, + Meta: &constant.Meta, } } case "enum": if constant.Value.Message.Enum == nil { return src.Const{}, &compiler.Error{ - Message: fmt.Sprintf("Enum value is missing in enum contant: %v", constant), - Location: scope.Location(), - Meta: &constant.Meta, + Message: fmt.Sprintf("Enum value is missing in enum contant: %v", constant), + Meta: &constant.Meta, } } if constant.Value.Message.Bool != nil || @@ -239,8 +220,7 @@ func (a Analyzer) analyzeConst( "Constant cannot have several values at once: %v", constant.Value.Message, ), - Location: scope.Location(), - Meta: &constant.Meta, + Meta: &constant.Meta, } } } diff --git a/internal/compiler/analyzer/interface.go b/internal/compiler/analyzer/interface.go index b7b5196e..5a916fd3 100644 --- a/internal/compiler/analyzer/interface.go +++ b/internal/compiler/analyzer/interface.go @@ -25,18 +25,16 @@ func (a Analyzer) analyzeInterface( resolvedParams, err := a.analyzeTypeParams(iface.TypeParams.Params, scope) if err != nil { return src.Interface{}, compiler.Error{ - Message: ErrInterfaceTypeParams.Error(), - Location: scope.Location(), - Meta: &iface.Meta, + Message: ErrInterfaceTypeParams.Error(), + Meta: &iface.Meta, }.Wrap(err) } resolvedIO, err := a.analyzeIO(resolvedParams, iface.IO, scope, params) if err != nil { return src.Interface{}, compiler.Error{ - Message: ErrInterfaceTypeParams.Error(), - Location: scope.Location(), - Meta: &iface.Meta, + Message: ErrInterfaceTypeParams.Error(), + Meta: &iface.Meta, }.Wrap(err) } @@ -60,31 +58,31 @@ func (a Analyzer) analyzeIO( ) (src.IO, *compiler.Error) { if !params.allowEmptyInports && len(io.In) == 0 { return src.IO{}, &compiler.Error{ - Message: "Interface must have inports", - Location: scope.Location(), + Message: "Interface must have inports", + Meta: &io.Meta, } } if !params.allowEmptyOutports && len(io.Out) == 0 { return src.IO{}, &compiler.Error{ - Message: "Interface must have outports", - Location: scope.Location(), + Message: "Interface must have outports", + Meta: &io.Meta, } } resolvedIn, err := a.analyzePorts(typeParams, io.In, scope) if err != nil { return src.IO{}, compiler.Error{ - Message: "Invalid inports", - Location: scope.Location(), + Message: "Invalid inports", + Meta: &io.Meta, }.Wrap(err) } resolvedOut, err := a.analyzePorts(typeParams, io.Out, scope) if err != nil { return src.IO{}, compiler.Error{ - Message: "Invalid outports", - Location: scope.Location(), + Message: "Invalid outports", + Meta: &io.Meta, }.Wrap(err) } @@ -104,8 +102,7 @@ func (a Analyzer) analyzePorts( resolvedPort, err := a.analyzePort(params, port, scope) if err != nil { return nil, compiler.Error{ - Location: scope.Location(), - Meta: &port.Meta, + Meta: &port.Meta, }.Wrap(err) } resolvedPorts[name] = resolvedPort @@ -124,8 +121,7 @@ func (a Analyzer) analyzePort(params []ts.Param, port src.Port, scope src.Scope) ) if err != nil { return src.Port{}, compiler.Error{ - Location: scope.Location(), - Meta: &port.Meta, + Meta: &port.Meta, }.Wrap(err) } diff --git a/internal/compiler/analyzer/main_component.go b/internal/compiler/analyzer/main_component.go index 73bf6999..8bc29663 100644 --- a/internal/compiler/analyzer/main_component.go +++ b/internal/compiler/analyzer/main_component.go @@ -11,7 +11,7 @@ func (a Analyzer) analyzeMainComponent(cmp src.Component, scope src.Scope) *comp if len(cmp.Interface.TypeParams.Params) != 0 { return &compiler.Error{ Message: "Main component cannot have type parameters", - Meta: &cmp.Interface.Meta, + Meta: &cmp.Interface.TypeParams.Meta, } } @@ -30,17 +30,19 @@ func (a Analyzer) analyzeMainFlowIO(io src.IO) *compiler.Error { if len(io.In) != 1 { return &compiler.Error{ Message: fmt.Sprintf("Main component must have exactly 1 inport: got %v", len(io.In)), + Meta: &io.Meta, } } if len(io.Out) != 1 { return &compiler.Error{ Message: fmt.Sprintf("Main component must have exactly 1 outport: got %v", len(io.Out)), + Meta: &io.Meta, } } enterInport, ok := io.In["start"] if !ok { - return &compiler.Error{Message: "Main component must have 'start' inport"} + return &compiler.Error{Message: "Main component must have 'start' inport", Meta: &io.Meta} } if err := a.analyzeMainComponentPort(enterInport); err != nil { @@ -49,11 +51,11 @@ func (a Analyzer) analyzeMainFlowIO(io src.IO) *compiler.Error { exitOutport, ok := io.Out["stop"] if !ok { - return &compiler.Error{Message: "Main component must have 'stop' outport"} + return &compiler.Error{Message: "Main component must have 'stop' outport", Meta: &io.Meta} } if err := a.analyzeMainComponentPort(exitOutport); err != nil { - return err + return compiler.Error{Meta: &exitOutport.Meta}.Wrap(err) } return nil @@ -80,20 +82,18 @@ func (Analyzer) analyzeMainComponentNodes( scope src.Scope, ) *compiler.Error { for nodeName, node := range nodes { - nodeEntity, loc, err := scope.Entity(node.EntityRef) + nodeEntity, _, err := scope.Entity(node.EntityRef) if err != nil { return &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), - Meta: &node.EntityRef.Meta, + Message: err.Error(), + Meta: &node.EntityRef.Meta, } } if nodeEntity.Kind != src.ComponentEntity { return &compiler.Error{ - Message: fmt.Sprintf("Main component's nodes must only refer to component entities: %v: %v", nodeName, node.EntityRef), - Location: &loc, - Meta: nodeEntity.Meta(), + Message: fmt.Sprintf("Main component's nodes must only refer to component entities: %v: %v", nodeName, node.EntityRef), + Meta: nodeEntity.Meta(), } } } diff --git a/internal/compiler/analyzer/main_pkg.go b/internal/compiler/analyzer/main_pkg.go index a94248b0..142b3c12 100644 --- a/internal/compiler/analyzer/main_pkg.go +++ b/internal/compiler/analyzer/main_pkg.go @@ -5,21 +5,24 @@ import ( "github.com/nevalang/neva/internal/compiler" src "github.com/nevalang/neva/internal/compiler/sourcecode" + "github.com/nevalang/neva/internal/compiler/sourcecode/core" ) func (a Analyzer) mainSpecificPkgValidation(mainPkgName string, mod src.Module, scope src.Scope) *compiler.Error { mainPkg := mod.Packages[mainPkgName] - location := src.Location{ - Module: scope.Location().Module, + location := core.Location{ + ModRef: scope.Location().ModRef, Package: mainPkgName, } entityMain, filename, ok := mainPkg.Entity("Main") if !ok { return &compiler.Error{ - Message: "Main entity is not found", - Location: &location, + Message: "Main entity is not found", + Meta: &core.Meta{ + Location: location, + }, } } @@ -27,16 +30,19 @@ func (a Analyzer) mainSpecificPkgValidation(mainPkgName string, mod src.Module, if entityMain.Kind != src.ComponentEntity { return &compiler.Error{ - Message: "Main entity must be a component", - Location: &location, + Message: "Main entity must be a component", + Meta: &core.Meta{ + Location: location, + }, } } if entityMain.IsPublic { return &compiler.Error{ - Message: "Main entity cannot be exported", - Location: &location, - Meta: &entityMain.Component.Meta, + Message: "Main entity cannot be exported", + Meta: &core.Meta{ + Location: location, + }, } } @@ -44,8 +50,7 @@ func (a Analyzer) mainSpecificPkgValidation(mainPkgName string, mod src.Module, if err := a.analyzeMainComponent(entityMain.Component, scope); err != nil { return compiler.Error{ - Location: &location, - Meta: &entityMain.Component.Meta, + Meta: &entityMain.Component.Meta, }.Wrap(err) } @@ -54,11 +59,6 @@ func (a Analyzer) mainSpecificPkgValidation(mainPkgName string, mod src.Module, return &compiler.Error{ Message: fmt.Sprintf("Unexpected public entity in main package: %v", result.EntityName), Meta: result.Entity.Meta(), - Location: &src.Location{ - Module: scope.Location().Module, - Package: mainPkgName, - Filename: result.FileName, - }, } } } diff --git a/internal/compiler/analyzer/network.go b/internal/compiler/analyzer/network.go index 9b8b85f2..37fafbb2 100644 --- a/internal/compiler/analyzer/network.go +++ b/internal/compiler/analyzer/network.go @@ -34,18 +34,17 @@ func (a Analyzer) analyzeNetwork( scope, ) if err != nil { - return nil, compiler.Error{Location: scope.Location()}.Wrap(err) + return nil, err } if err := a.analyzeNetPortsUsage( compInterface, nodesIfaces, hasGuard, - scope, nodesUsage, nodes, ); err != nil { - return nil, compiler.Error{Location: scope.Location()}.Wrap(err) + return nil, err } return analyzedConnections, nil @@ -286,9 +285,8 @@ func (a Analyzer) analyzeReceiver( } return nil, &compiler.Error{ - Message: "Connection must have receiver-side", - Location: scope.Location(), - Meta: &receiver.Meta, + Message: "Connection must have receiver-side", + Meta: &receiver.Meta, } } @@ -317,9 +315,8 @@ func (a Analyzer) analyzeSwitchReceiver( ) if err != nil { return nil, nil, &compiler.Error{ - Message: fmt.Sprintf("Invalid switch case: %v", err), - Location: scope.Location(), - Meta: &switchConn.Meta, + Message: fmt.Sprintf("Invalid switch case: %v", err), + Meta: &switchConn.Meta, } } @@ -338,9 +335,8 @@ func (a Analyzer) analyzeSwitchReceiver( ) if err != nil { return nil, nil, &compiler.Error{ - Message: fmt.Sprintf("Invalid switch case sender: %v", err), - Location: scope.Location(), - Meta: &switchSender.Meta, + Message: fmt.Sprintf("Invalid switch case sender: %v", err), + Meta: &switchSender.Meta, } } @@ -351,8 +347,7 @@ func (a Analyzer) analyzeSwitchReceiver( "Incompatible types in switch: %v -> %v: %v", analyzedSenders[i], switchSender, err.Error(), ), - Location: scope.Location(), - Meta: &switchSender.Meta, + Meta: &switchSender.Meta, } } } @@ -361,9 +356,8 @@ func (a Analyzer) analyzeSwitchReceiver( if receiver.Switch.Default == nil { return nil, nil, &compiler.Error{ - Message: "Switch must have a default case", - Location: scope.Location(), - Meta: &receiver.Meta, + Message: "Switch must have a default case", + Meta: &receiver.Meta, } } @@ -403,24 +397,21 @@ func (a Analyzer) analyzePortAddrReceiver( ) if err != nil { return compiler.Error{ - Location: scope.Location(), - Meta: &portAddr.Meta, + Meta: &portAddr.Meta, }.Wrap(err) } if !isArrPort && portAddr.Idx != nil { return &compiler.Error{ - Message: "Index for non-array port", - Meta: &portAddr.Meta, - Location: scope.Location(), + Message: "Index for non-array port", + Meta: &portAddr.Meta, } } if isArrPort && portAddr.Idx == nil { return &compiler.Error{ - Message: "Index needed for array inport", - Meta: &portAddr.Meta, - Location: scope.Location(), + Message: "Index needed for array inport", + Meta: &portAddr.Meta, } } @@ -431,8 +422,7 @@ func (a Analyzer) analyzePortAddrReceiver( "Incompatible types: %v -> %v: %v", analyzedSenders[i], portAddr, err.Error(), ), - Location: scope.Location(), - Meta: &portAddr.Meta, + Meta: &portAddr.Meta, } } } @@ -442,9 +432,8 @@ func (a Analyzer) analyzePortAddrReceiver( // otherwise desugarer won't be able to properly desugar such port-addresses if err := netNodesUsage(nodesUsage).trackInportUsage(resolvedPortAddr); err != nil { return &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), - Meta: &portAddr.Meta, + Message: err.Error(), + Meta: &portAddr.Meta, } } @@ -463,17 +452,15 @@ func (a Analyzer) analyzeChainedConnectionReceiver( ) (src.Connection, *compiler.Error) { if chainedConn.Normal == nil { return src.Connection{}, &compiler.Error{ - Message: "chained connection must be a normal connection", - Location: scope.Location(), - Meta: &chainedConn.Meta, + Message: "chained connection must be a normal connection", + Meta: &chainedConn.Meta, } } if len(chainedConn.Normal.Senders) != 1 { return src.Connection{}, &compiler.Error{ - Message: "multiple senders are only allowed at the start of a connection", - Location: scope.Location(), - Meta: &chainedConn.Normal.Meta, + Message: "multiple senders are only allowed at the start of a connection", + Meta: &chainedConn.Normal.Meta, } } @@ -496,8 +483,7 @@ func (a Analyzer) analyzeChainedConnectionReceiver( "Incompatible types: %v -> %v: %v", analyzedSenders[i], chainHead, err.Error(), ), - Location: scope.Location(), - Meta: &chainedConn.Meta, + Meta: &chainedConn.Meta, } } } @@ -518,9 +504,8 @@ func (a Analyzer) analyzeChainedConnectionReceiver( if chainHead.PortAddr != nil { if err := netNodesUsage(nodesUsage).trackInportUsage(*chainHead.PortAddr); err != nil { return src.Connection{}, &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), - Meta: &chainedConn.Meta, + Message: err.Error(), + Meta: &chainedConn.Meta, } } } @@ -552,8 +537,7 @@ func (a Analyzer) analyzeSenders( ) if err != nil { return nil, nil, compiler.Error{ - Location: scope.Location(), - Meta: &sender.Meta, + Meta: &sender.Meta, }.Wrap(err) } @@ -586,9 +570,8 @@ func (a Analyzer) analyzeSender( sender.Ternary == nil && len(sender.StructSelector) == 0 { return nil, nil, &compiler.Error{ - Message: "Sender in network must contain port address, constant reference or message literal", - Location: scope.Location(), - Meta: &sender.Meta, + Message: "Sender in network must contain port address, constant reference or message literal", + Meta: &sender.Meta, } } @@ -596,17 +579,15 @@ func (a Analyzer) analyzeSender( if sender.Range != nil && len(prevChainLink) == 0 { return nil, nil, &compiler.Error{ - Message: "range expression cannot be used in non-chained connection", - Location: scope.Location(), - Meta: &sender.Meta, + Message: "range expression cannot be used in non-chained connection", + Meta: &sender.Meta, } } if len(sender.StructSelector) > 0 && len(prevChainLink) == 0 { return nil, nil, &compiler.Error{ - Message: "struct selectors cannot be used in non-chained connection", - Location: scope.Location(), - Meta: &sender.Meta, + Message: "struct selectors cannot be used in non-chained connection", + Meta: &sender.Meta, } } @@ -623,8 +604,7 @@ func (a Analyzer) analyzeSender( ) if err != nil { return nil, nil, compiler.Error{ - Location: scope.Location(), - Meta: &sender.Ternary.Meta, + Meta: &sender.Ternary.Meta, }.Wrap(err) } @@ -634,9 +614,8 @@ func (a Analyzer) analyzeSender( } if err := a.resolver.IsSubtypeOf(*condType, boolType, scope); err != nil { return nil, nil, &compiler.Error{ - Message: "Condition of ternary expression must be of boolean type", - Location: scope.Location(), - Meta: &sender.Ternary.Meta, + Message: "Condition of ternary expression must be of boolean type", + Meta: &sender.Ternary.Meta, } } @@ -652,8 +631,7 @@ func (a Analyzer) analyzeSender( ) if err != nil { return nil, nil, compiler.Error{ - Location: scope.Location(), - Meta: &sender.Ternary.Meta, + Meta: &sender.Ternary.Meta, }.Wrap(err) } @@ -669,8 +647,7 @@ func (a Analyzer) analyzeSender( ) if err != nil { return nil, nil, compiler.Error{ - Location: scope.Location(), - Meta: &sender.Ternary.Meta, + Meta: &sender.Ternary.Meta, }.Wrap(err) } @@ -704,24 +681,22 @@ func (a Analyzer) analyzeSender( return nil, nil, err } - constr, err := a.getOperatorConstraint(*sender.Binary, scope) + constr, err := a.getOperatorConstraint(*sender.Binary) if err != nil { return nil, nil, err } if err := a.resolver.IsSubtypeOf(*leftType, constr, scope); err != nil { return nil, nil, &compiler.Error{ - Message: fmt.Sprintf("Invalid left operand type for %s: %v", sender.Binary.Operator, err), - Location: scope.Location(), - Meta: &sender.Binary.Meta, + Message: fmt.Sprintf("Invalid left operand type for %s: %v", sender.Binary.Operator, err), + Meta: &sender.Binary.Meta, } } if err := a.resolver.IsSubtypeOf(*rightType, constr, scope); err != nil { return nil, nil, &compiler.Error{ - Message: fmt.Sprintf("Invalid right operand type for %s: %v", sender.Binary.Operator, err), - Location: scope.Location(), - Meta: &sender.Binary.Meta, + Message: fmt.Sprintf("Invalid right operand type for %s: %v", sender.Binary.Operator, err), + Meta: &sender.Binary.Meta, } } @@ -744,33 +719,29 @@ func (a Analyzer) analyzeSender( ) if err != nil { return nil, nil, compiler.Error{ - Location: scope.Location(), - Meta: &sender.Meta, + Meta: &sender.Meta, }.Wrap(err) } if sender.PortAddr != nil { if !isSenderArr && sender.PortAddr.Idx != nil { return nil, nil, &compiler.Error{ - Message: "Index for non-array port", - Meta: &sender.PortAddr.Meta, - Location: scope.Location(), + Message: "Index for non-array port", + Meta: &sender.PortAddr.Meta, } } if isSenderArr && sender.PortAddr.Idx == nil { return nil, nil, &compiler.Error{ - Message: "Index needed for array outport", - Meta: &sender.PortAddr.Meta, - Location: scope.Location(), + Message: "Index needed for array outport", + Meta: &sender.PortAddr.Meta, } } if sender.PortAddr.Port == "err" && nodes[sender.PortAddr.Node].ErrGuard { return nil, nil, &compiler.Error{ - Message: "if node has error guard '?' it's ':err' outport must not be explicitly used in the network", - Meta: &sender.PortAddr.Meta, - Location: scope.Location(), + Message: "if node has error guard '?' it's ':err' outport must not be explicitly used in the network", + Meta: &sender.PortAddr.Meta, } } @@ -780,9 +751,8 @@ func (a Analyzer) analyzeSender( // otherwise desugarer won't be able to properly desugar such port-addresses if err := netNodesUsage(nodesUsage).trackOutportUsage(*resolvedSenderAddr.PortAddr); err != nil { return nil, nil, &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), - Meta: &sender.PortAddr.Meta, + Message: err.Error(), + Meta: &sender.PortAddr.Meta, } } @@ -814,15 +784,13 @@ func (a Analyzer) analyzeArrayBypassConnection( ) if err != nil { return compiler.Error{ - Location: scope.Location(), - Meta: &conn.Meta, + Meta: &conn.Meta, }.Wrap(err) } if !isArray { return &compiler.Error{ - Message: "Non-array outport in array-bypass connection", - Location: scope.Location(), - Meta: &arrBypassConn.SenderOutport.Meta, + Message: "Non-array outport in array-bypass connection", + Meta: &arrBypassConn.SenderOutport.Meta, } } @@ -835,15 +803,13 @@ func (a Analyzer) analyzeArrayBypassConnection( ) if err != nil { return compiler.Error{ - Location: scope.Location(), - Meta: &conn.Meta, + Meta: &conn.Meta, }.Wrap(err) } if !isArray { return &compiler.Error{ - Message: "Non-array outport in array-bypass connection", - Location: scope.Location(), - Meta: &arrBypassConn.SenderOutport.Meta, + Message: "Non-array outport in array-bypass connection", + Meta: &arrBypassConn.SenderOutport.Meta, } } @@ -857,24 +823,21 @@ func (a Analyzer) analyzeArrayBypassConnection( "Incompatible types: %v -> %v: %v", arrBypassConn.SenderOutport, arrBypassConn.ReceiverInport, err.Error(), ), - Location: scope.Location(), - Meta: &conn.Meta, + Meta: &conn.Meta, } } if err := netNodesUsage(nodesUsage).trackOutportUsage(arrBypassConn.SenderOutport); err != nil { return &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), - Meta: &conn.Meta, + Message: err.Error(), + Meta: &conn.Meta, } } if err := netNodesUsage(nodesUsage).trackInportUsage(arrBypassConn.ReceiverInport); err != nil { return &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), - Meta: &conn.Meta, + Message: err.Error(), + Meta: &conn.Meta, } } @@ -885,7 +848,6 @@ func (a Analyzer) analyzeNetPortsUsage( compInterface src.Interface, nodesIfaces map[string]foundInterface, hasGuard bool, - scope src.Scope, nodesUsage map[string]netNodeUsage, nodes map[string]src.Node, ) *compiler.Error { @@ -893,17 +855,15 @@ func (a Analyzer) analyzeNetPortsUsage( inportsUsage, ok := nodesUsage["in"] if !ok { return &compiler.Error{ - Message: "Unused inports", - Location: scope.Location(), - Meta: &compInterface.Meta, + Message: "Unused inports", + Meta: &compInterface.Meta, } } for inportName := range compInterface.IO.In { if _, ok := inportsUsage.Out[inportName]; !ok { // note that self inports are outports for the network return &compiler.Error{ - Message: fmt.Sprintf("Unused inport: %v", inportName), - Location: scope.Location(), + Message: fmt.Sprintf("Unused inport: %v", inportName), } } } @@ -912,9 +872,8 @@ func (a Analyzer) analyzeNetPortsUsage( outportsUsage, ok := nodesUsage["out"] if !ok { return &compiler.Error{ - Message: "Component must use its outports", - Location: scope.Location(), - Meta: &compInterface.Meta, + Message: "Component must use its outports", + Meta: &compInterface.Meta, } } @@ -929,8 +888,7 @@ func (a Analyzer) analyzeNetPortsUsage( } return &compiler.Error{ - Message: fmt.Sprintf("Unused outport: %v", outportName), - Location: scope.Location(), + Message: fmt.Sprintf("Unused outport: %v", outportName), } } @@ -942,9 +900,8 @@ func (a Analyzer) analyzeNetPortsUsage( nodeUsage, ok := nodesUsage[nodeName] if !ok { return &compiler.Error{ - Message: fmt.Sprintf("Unused node found: %v", nodeName), - Location: scope.Location(), - Meta: &nodeMeta, + Message: fmt.Sprintf("Unused node found: %v", nodeName), + Meta: &nodeMeta, } } @@ -965,8 +922,7 @@ func (a Analyzer) analyzeNetPortsUsage( nodeName, inportName, ), - Location: scope.Location(), - Meta: &nodeMeta, + Meta: &nodeMeta, } } @@ -984,9 +940,8 @@ func (a Analyzer) analyzeNetPortsUsage( if outportName == "err" && !nodes[nodeName].ErrGuard { return &compiler.Error{ - Message: fmt.Sprintf("unhandled error: %v:err", nodeName), - Location: scope.Location(), - Meta: &nodeMeta, + Message: fmt.Sprintf("unhandled error: %v:err", nodeName), + Meta: &nodeMeta, } } } @@ -996,9 +951,8 @@ func (a Analyzer) analyzeNetPortsUsage( continue } return &compiler.Error{ - Message: fmt.Sprintf("All node's outports are unused: %v", nodeName), - Location: scope.Location(), - Meta: &nodeMeta, + Message: fmt.Sprintf("All node's outports are unused: %v", nodeName), + Meta: &nodeMeta, } } } @@ -1028,8 +982,7 @@ func (a Analyzer) analyzeNetPortsUsage( portName, i, ), - Location: scope.Location(), - Meta: &nodeMeta, + Meta: &nodeMeta, } } } @@ -1056,8 +1009,7 @@ func (a Analyzer) analyzeNetPortsUsage( portName, i, ), - Location: scope.Location(), - Meta: &nodeMeta, + Meta: &nodeMeta, } } } @@ -1078,9 +1030,8 @@ func (a Analyzer) getReceiverPortType( ) (src.PortAddr, ts.Expr, bool, *compiler.Error) { if receiverSide.Node == "in" { return src.PortAddr{}, ts.Expr{}, false, &compiler.Error{ - Message: "Component cannot read from self inport", - Location: scope.Location(), - Meta: &receiverSide.Meta, + Message: "Component cannot read from self inport", + Meta: &receiverSide.Meta, } } @@ -1090,9 +1041,8 @@ func (a Analyzer) getReceiverPortType( outport, ok := outports[receiverSide.Port] if !ok { return src.PortAddr{}, ts.Expr{}, false, &compiler.Error{ - Message: fmt.Sprintf("Referenced inport not found in component's interface: %v", receiverSide.Port), - Location: scope.Location(), - Meta: &receiverSide.Meta, + Message: fmt.Sprintf("Referenced inport not found in component's interface: %v", receiverSide.Port), + Meta: &receiverSide.Meta, } } @@ -1103,9 +1053,8 @@ func (a Analyzer) getReceiverPortType( ) if err != nil { return src.PortAddr{}, ts.Expr{}, false, &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), - Meta: &receiverSide.Meta, + Message: err.Error(), + Meta: &receiverSide.Meta, } } @@ -1117,8 +1066,7 @@ func (a Analyzer) getReceiverPortType( ) if err != nil { return src.PortAddr{}, ts.Expr{}, false, compiler.Error{ - Location: scope.Location(), - Meta: &receiverSide.Meta, + Meta: &receiverSide.Meta, }.Wrap(err) } @@ -1136,18 +1084,16 @@ func (a Analyzer) getNodeInportType( node, ok := nodes[portAddr.Node] if !ok { return src.PortAddr{}, ts.Expr{}, false, &compiler.Error{ - Message: fmt.Sprintf("Node not found '%v'", portAddr.Node), - Location: scope.Location(), - Meta: &portAddr.Meta, + Message: fmt.Sprintf("Node not found '%v'", portAddr.Node), + Meta: &portAddr.Meta, } } nodeIface, ok := nodesIfaces[portAddr.Node] if !ok { return src.PortAddr{}, ts.Expr{}, false, &compiler.Error{ - Message: fmt.Sprintf("Referenced node not found: %v", portAddr.Node), - Location: scope.Location(), - Meta: &portAddr.Meta, + Message: fmt.Sprintf("Referenced node not found: %v", portAddr.Node), + Meta: &portAddr.Meta, } } @@ -1161,8 +1107,7 @@ func (a Analyzer) getNodeInportType( ) if err != nil { return src.PortAddr{}, ts.Expr{}, false, compiler.Error{ - Location: scope.Location(), - Meta: &portAddr.Meta, + Meta: &portAddr.Meta, }.Wrap(err) } @@ -1187,9 +1132,8 @@ func (a Analyzer) getResolvedPortType( } } else { return src.PortAddr{}, ts.Expr{}, false, &compiler.Error{ - Message: fmt.Sprintf("node '%v' has multiple ports - port name must be specified", portAddr.Node), - Location: scope.Location(), - Meta: &portAddr.Meta, + Message: fmt.Sprintf("node '%v' has multiple ports - port name must be specified", portAddr.Node), + Meta: &portAddr.Meta, } } } @@ -1198,11 +1142,10 @@ func (a Analyzer) getResolvedPortType( if !ok { return src.PortAddr{}, ts.Expr{}, false, &compiler.Error{ Message: fmt.Sprintf( - "Port not found `%v`", + "Port not found '%v'", portAddr, ), - Location: scope.Location(), - Meta: &portAddr.Meta, + Meta: &portAddr.Meta, } } @@ -1225,9 +1168,8 @@ func (a Analyzer) getResolvedPortType( ) if err != nil { return src.PortAddr{}, ts.Expr{}, false, &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), - Meta: &port.Meta, + Message: err.Error(), + Meta: &port.Meta, } } @@ -1287,8 +1229,7 @@ func (a Analyzer) getResolvedSenderType( ) if err != nil { return src.ConnectionSender{}, ts.Expr{}, false, compiler.Error{ - Location: scope.Location(), - Meta: &sender.Meta, + Meta: &sender.Meta, }.Wrap(err) } @@ -1324,8 +1265,7 @@ func (a Analyzer) getResolvedSenderType( ) if err != nil { return src.ConnectionSender{}, ts.Expr{}, false, compiler.Error{ - Location: scope.Location(), - Meta: &sender.Ternary.Meta, + Meta: &sender.Ternary.Meta, }.Wrap(err) } // FIXME: perfectly we need to return union, but it's not yet supported @@ -1368,7 +1308,7 @@ func (Analyzer) getBinaryExprType(operator src.BinaryOperator, leftType ts.Expr) return leftType } -func (Analyzer) getOperatorConstraint(binary src.Binary, scope src.Scope) (ts.Expr, *compiler.Error) { +func (Analyzer) getOperatorConstraint(binary src.Binary) (ts.Expr, *compiler.Error) { switch binary.Operator { case src.AddOp: return ts.Expr{ @@ -1421,8 +1361,7 @@ func (Analyzer) getOperatorConstraint(binary src.Binary, scope src.Scope) (ts.Ex "Unsupported binary operator: %v", binary.Operator, ), - Location: scope.Location(), - Meta: &binary.Meta, + Meta: &binary.Meta, } } } @@ -1438,9 +1377,8 @@ func (a Analyzer) getPortSenderType( ) (src.PortAddr, ts.Expr, bool, *compiler.Error) { if senderSidePortAddr.Node == "out" { return src.PortAddr{}, ts.Expr{}, false, &compiler.Error{ - Message: "Component cannot read from self outport", - Location: scope.Location(), - Meta: &senderSidePortAddr.Meta, + Message: "Component cannot read from self outport", + Meta: &senderSidePortAddr.Meta, } } @@ -1450,9 +1388,8 @@ func (a Analyzer) getPortSenderType( inport, ok := inports[senderSidePortAddr.Port] if !ok { return src.PortAddr{}, ts.Expr{}, false, &compiler.Error{ - Message: fmt.Sprintf("Referenced inport not found in component's interface: %v", senderSidePortAddr.Port), - Location: scope.Location(), - Meta: &senderSidePortAddr.Meta, + Message: fmt.Sprintf("Referenced inport not found in component's interface: %v", senderSidePortAddr.Port), + Meta: &senderSidePortAddr.Meta, } } @@ -1463,9 +1400,8 @@ func (a Analyzer) getPortSenderType( ) if err != nil { return src.PortAddr{}, ts.Expr{}, false, &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), - Meta: &senderSidePortAddr.Meta, + Message: err.Error(), + Meta: &senderSidePortAddr.Meta, } } @@ -1485,8 +1421,7 @@ func (a Analyzer) getConstSenderType( expr, err := a.getResolvedConstTypeByRef(*constSender.Value.Ref, scope) if err != nil { return src.Const{}, ts.Expr{}, compiler.Error{ - Location: scope.Location(), - Meta: &constSender.Value.Ref.Meta, + Meta: &constSender.Value.Ref.Meta, }.Wrap(err) } return constSender, expr, nil @@ -1494,9 +1429,8 @@ func (a Analyzer) getConstSenderType( if constSender.Value.Message == nil { return src.Const{}, ts.Expr{}, &compiler.Error{ - Message: "Literal sender type is empty", - Location: scope.Location(), - Meta: &constSender.Meta, + Message: "Literal sender type is empty", + Meta: &constSender.Meta, } } @@ -1506,17 +1440,15 @@ func (a Analyzer) getConstSenderType( ) if err != nil { return src.Const{}, ts.Expr{}, &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), - Meta: &constSender.Value.Message.Meta, + Message: err.Error(), + Meta: &constSender.Value.Message.Meta, } } if err := a.validateLiteralSender(resolvedExpr); err != nil { return src.Const{}, ts.Expr{}, &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), - Meta: &constSender.Value.Message.Meta, + Message: err.Error(), + Meta: &constSender.Value.Message.Meta, } } @@ -1566,18 +1498,16 @@ func (a Analyzer) getNodeOutportType( node, ok := nodes[portAddr.Node] if !ok { return src.PortAddr{}, ts.Expr{}, false, &compiler.Error{ - Message: fmt.Sprintf("Referenced node not found: %v", portAddr.Node), - Location: scope.Location(), - Meta: &portAddr.Meta, + Message: fmt.Sprintf("Referenced node not found: %v", portAddr.Node), + Meta: &portAddr.Meta, } } nodeIface, ok := nodesIfaces[portAddr.Node] if !ok { return src.PortAddr{}, ts.Expr{}, false, &compiler.Error{ - Message: fmt.Sprintf("Referenced node not found: %v", portAddr.Node), - Location: scope.Location(), - Meta: &portAddr.Meta, + Message: fmt.Sprintf("Referenced node not found: %v", portAddr.Node), + Meta: &portAddr.Meta, } } @@ -1595,17 +1525,15 @@ func (a Analyzer) getResolvedConstTypeByRef(ref core.EntityRef, scope src.Scope) entity, location, err := scope.Entity(ref) if err != nil { return ts.Expr{}, &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), - Meta: &ref.Meta, + Message: err.Error(), + Meta: &ref.Meta, } } if entity.Kind != src.ConstEntity { return ts.Expr{}, &compiler.Error{ - Message: fmt.Sprintf("%v: %v", errors.New("Entity found but is not constant"), entity.Kind), - Location: &location, - Meta: entity.Meta(), + Message: fmt.Sprintf("%v: %v", errors.New("Entity found but is not constant"), entity.Kind), + Meta: entity.Meta(), } } @@ -1613,8 +1541,7 @@ func (a Analyzer) getResolvedConstTypeByRef(ref core.EntityRef, scope src.Scope) expr, err := a.getResolvedConstTypeByRef(*entity.Const.Value.Ref, scope) if err != nil { return ts.Expr{}, compiler.Error{ - Location: &location, - Meta: &entity.Const.Meta, + Meta: &entity.Const.Meta, }.Wrap(err) } return expr, nil @@ -1625,9 +1552,8 @@ func (a Analyzer) getResolvedConstTypeByRef(ref core.EntityRef, scope src.Scope) resolvedExpr, err := a.resolver.ResolveExpr(entity.Const.TypeExpr, scope) if err != nil { return ts.Expr{}, &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), - Meta: &entity.Const.Value.Message.Meta, + Message: err.Error(), + Meta: &entity.Const.Value.Message.Meta, } } @@ -1645,8 +1571,7 @@ func (a Analyzer) getSelectorsSenderType( if senderType.Lit == nil || senderType.Lit.Struct == nil { return ts.Expr{}, &compiler.Error{ - Message: fmt.Sprintf("Type not struct: %v", senderType.String()), - Location: scope.Location(), + Message: fmt.Sprintf("Type not struct: %v", senderType.String()), } } @@ -1654,8 +1579,7 @@ func (a Analyzer) getSelectorsSenderType( fieldType, ok := senderType.Lit.Struct[curField] if !ok { return ts.Expr{}, &compiler.Error{ - Message: fmt.Sprintf("struct field '%v' not found", curField), - Location: scope.Location(), + Message: fmt.Sprintf("struct field '%v' not found", curField), } } @@ -1702,9 +1626,8 @@ func (a Analyzer) getChainHeadType( } return ts.Expr{}, &compiler.Error{ - Message: "Chained connection must start with port address or range expression", - Location: scope.Location(), - Meta: &chainHead.Meta, + Message: "Chained connection must start with port address or range expression", + Meta: &chainHead.Meta, } } diff --git a/internal/compiler/analyzer/nodes.go b/internal/compiler/analyzer/nodes.go index a52f9329..f6b9cfdb 100644 --- a/internal/compiler/analyzer/nodes.go +++ b/internal/compiler/analyzer/nodes.go @@ -11,7 +11,7 @@ import ( type foundInterface struct { iface src.Interface - location src.Location + location core.Location } func (a Analyzer) analyzeNodes( @@ -40,8 +40,7 @@ func (a Analyzer) analyzeNodes( ) if err != nil { return nil, nil, false, compiler.Error{ - Location: scope.Location(), - Meta: &node.Meta, + Meta: &node.Meta, }.Wrap(err) } @@ -62,27 +61,24 @@ func (a Analyzer) analyzeNode( nodeEntity, location, err := scope.Entity(node.EntityRef) if err != nil { return src.Node{}, foundInterface{}, &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), - Meta: &node.Meta, + Message: err.Error(), + Meta: &node.Meta, } } if nodeEntity.Kind != src.ComponentEntity && nodeEntity.Kind != src.InterfaceEntity { return src.Node{}, foundInterface{}, &compiler.Error{ - Message: fmt.Sprintf("Node can only refer to flows or interfaces: %v", nodeEntity.Kind), - Location: &location, - Meta: nodeEntity.Meta(), + Message: fmt.Sprintf("Node can only refer to flows or interfaces: %v", nodeEntity.Kind), + Meta: nodeEntity.Meta(), } } bindDirectiveArgs, usesBindDirective := node.Directives[compiler.BindDirective] if usesBindDirective && len(bindDirectiveArgs) != 1 { return src.Node{}, foundInterface{}, &compiler.Error{ - Message: "Node with #bind directive must provide exactly one argument", - Location: &location, - Meta: nodeEntity.Meta(), + Message: "Node with #bind directive must provide exactly one argument", + Meta: nodeEntity.Meta(), } } @@ -95,9 +91,8 @@ func (a Analyzer) analyzeNode( ) if err != nil { return src.Node{}, foundInterface{}, &compiler.Error{ - Message: err.Error(), - Location: &location, - Meta: &node.Meta, + Message: err.Error(), + Meta: &node.Meta, } } @@ -111,16 +106,14 @@ func (a Analyzer) analyzeNode( ) if err != nil { return src.Node{}, foundInterface{}, &compiler.Error{ - Message: err.Error(), - Location: &location, - Meta: &node.Meta, + Message: err.Error(), + Meta: &node.Meta, } } nodeIface, aerr := a.getNodeInterface( nodeEntity, usesBindDirective, - location, node, scope, resolvedNodeArgs, @@ -132,16 +125,14 @@ func (a Analyzer) analyzeNode( if node.ErrGuard { if _, ok := compIface.IO.Out["err"]; !ok { return src.Node{}, foundInterface{}, &compiler.Error{ - Message: "Error-guard operator '?' can only be used in components with ':err' outport to propagate errors", - Location: scope.Location(), - Meta: &node.Meta, + Message: "Error-guard operator '?' can only be used in components with ':err' outport to propagate errors", + Meta: &node.Meta, } } if _, ok := nodeIface.IO.Out["err"]; !ok { return src.Node{}, foundInterface{}, &compiler.Error{ - Message: "Error-guard operator '?' requires node to have ':err' outport to propagate errors", - Location: scope.Location(), - Meta: &node.Meta, + Message: "Error-guard operator '?' requires node to have ':err' outport to propagate errors", + Meta: &node.Meta, } } } @@ -165,9 +156,8 @@ func (a Analyzer) analyzeNode( scope, ); err != nil { return src.Node{}, foundInterface{}, &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), - Meta: &node.Meta, + Message: err.Error(), + Meta: &node.Meta, } } @@ -197,8 +187,7 @@ func (a Analyzer) analyzeNode( ) if err != nil { return src.Node{}, foundInterface{}, compiler.Error{ - Location: &location, - Meta: &depNode.Meta, + Meta: &depNode.Meta, }.Wrap(err) } resolvedFlowDI[depName] = resolvedDep @@ -221,7 +210,6 @@ func (a Analyzer) analyzeNode( func (a Analyzer) getNodeInterface( entity src.Entity, usesBindDirective bool, - location src.Location, node src.Node, scope src.Scope, resolvedNodeArgs []typesystem.Expr, @@ -229,17 +217,15 @@ func (a Analyzer) getNodeInterface( if entity.Kind == src.InterfaceEntity { if usesBindDirective { return src.Interface{}, &compiler.Error{ - Message: "Interface node cannot use #bind directive", - Location: &location, - Meta: entity.Meta(), + Message: "Interface node cannot use #bind directive", + Meta: entity.Meta(), } } if node.DIArgs != nil { return src.Interface{}, &compiler.Error{ - Message: "Only component node can have dependency injection", - Location: &location, - Meta: entity.Meta(), + Message: "Only component node can have dependency injection", + Meta: entity.Meta(), } } @@ -250,17 +236,15 @@ func (a Analyzer) getNodeInterface( if usesBindDirective && !hasExternDirective { return src.Interface{}, &compiler.Error{ - Message: "Node can't use #bind if it isn't instantiated with the component that use #extern", - Location: &location, - Meta: entity.Meta(), + Message: "Node can't use #bind if it isn't instantiated with the component that use #extern", + Meta: entity.Meta(), } } if len(externArgs) > 1 && len(resolvedNodeArgs) != 1 { return src.Interface{}, &compiler.Error{ - Message: "Component that use #extern directive with > 1 argument, must have exactly one type-argument for overloading", - Location: &location, - Meta: entity.Meta(), + Message: "Component that use #extern directive with > 1 argument, must have exactly one type-argument for overloading", + Meta: entity.Meta(), } } @@ -275,59 +259,52 @@ func (a Analyzer) getNodeInterface( if len(iface.IO.In) != 0 { return src.Interface{}, &compiler.Error{ - Message: "Component that uses struct inports directive must have no defined inports", - Location: &location, - Meta: entity.Meta(), + Message: "Component that uses struct inports directive must have no defined inports", + Meta: entity.Meta(), } } if len(iface.TypeParams.Params) != 1 { return src.Interface{}, &compiler.Error{ - Message: "Exactly one type parameter expected", - Location: &location, - Meta: entity.Meta(), + Message: "Exactly one type parameter expected", + Meta: entity.Meta(), } } resolvedTypeParamConstr, err := a.resolver.ResolveExpr(iface.TypeParams.Params[0].Constr, scope) if err != nil { return src.Interface{}, &compiler.Error{ - Message: err.Error(), - Location: &location, - Meta: entity.Meta(), + Message: err.Error(), + Meta: entity.Meta(), } } if resolvedTypeParamConstr.Lit == nil || resolvedTypeParamConstr.Lit.Struct == nil { return src.Interface{}, &compiler.Error{ - Message: "Struct type expected", - Location: &location, - Meta: entity.Meta(), + Message: "Struct type expected", + Meta: entity.Meta(), } } if len(resolvedNodeArgs) != 1 { return src.Interface{}, &compiler.Error{ - Message: "Exactly one type argument expected", - Location: &location, - Meta: entity.Meta(), + Message: "Exactly one type argument expected", + Meta: entity.Meta(), } } resolvedNodeArg, err := a.resolver.ResolveExpr(resolvedNodeArgs[0], scope) if err != nil { return src.Interface{}, &compiler.Error{ - Message: err.Error(), - Location: &location, - Meta: entity.Meta(), + Message: err.Error(), + Meta: entity.Meta(), } } if resolvedNodeArg.Lit == nil || resolvedNodeArg.Lit.Struct == nil { return src.Interface{}, &compiler.Error{ - Message: "Struct argument expected", - Location: &location, - Meta: entity.Meta(), + Message: "Struct argument expected", + Meta: entity.Meta(), } } diff --git a/internal/compiler/analyzer/semver.go b/internal/compiler/analyzer/semver.go index 44616c53..1c18553d 100644 --- a/internal/compiler/analyzer/semver.go +++ b/internal/compiler/analyzer/semver.go @@ -7,12 +7,13 @@ import ( "github.com/nevalang/neva/internal/compiler" src "github.com/nevalang/neva/internal/compiler/sourcecode" + "github.com/nevalang/neva/internal/compiler/sourcecode/core" "github.com/nevalang/neva/pkg" ) // semverCheck ensures that module is compatible with existing compiler // by checking it's version against semver. It uses minor as major. -func (a Analyzer) semverCheck(mod src.Module, modRef src.ModuleRef) *compiler.Error { +func (a Analyzer) semverCheck(mod src.Module, modRef core.ModuleRef) *compiler.Error { moduleVersion, semverErr := semver.NewVersion(mod.Manifest.LanguageVersion) if semverErr != nil { return &compiler.Error{ diff --git a/internal/compiler/analyzer/type.go b/internal/compiler/analyzer/type.go index d0a10bec..6f80322e 100644 --- a/internal/compiler/analyzer/type.go +++ b/internal/compiler/analyzer/type.go @@ -3,7 +3,6 @@ package analyzer import ( "github.com/nevalang/neva/internal/compiler" src "github.com/nevalang/neva/internal/compiler/sourcecode" - "github.com/nevalang/neva/internal/compiler/sourcecode/core" ts "github.com/nevalang/neva/internal/compiler/sourcecode/typesystem" ) @@ -13,11 +12,10 @@ type analyzeTypeDefParams struct { func (a Analyzer) analyzeTypeDef(def ts.Def, scope src.Scope, params analyzeTypeDefParams) (ts.Def, *compiler.Error) { if !params.allowEmptyBody && def.BodyExpr == nil { - meta := def.Meta.(core.Meta) //nolint:forcetypeassert + meta := def.Meta return ts.Def{}, &compiler.Error{ - Message: "Type definition must have non-empty body", - Location: scope.Location(), - Meta: &meta, + Message: "Type definition must have non-empty body", + Meta: &meta, } } @@ -25,11 +23,10 @@ func (a Analyzer) analyzeTypeDef(def ts.Def, scope src.Scope, params analyzeType // We can't resolve body without args. And don't worry about unused bodies. Unused entities are error themselves. resolvedParams, _, err := a.resolver.ResolveParams(def.Params, scope) if err != nil { - meta := def.Meta.(core.Meta) //nolint:forcetypeassert + meta := def.Meta return ts.Def{}, &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), - Meta: &meta, + Message: err.Error(), + Meta: &meta, } } @@ -42,11 +39,10 @@ func (a Analyzer) analyzeTypeDef(def ts.Def, scope src.Scope, params analyzeType func (a Analyzer) analyzeTypeExpr(expr ts.Expr, scope src.Scope) (ts.Expr, *compiler.Error) { resolvedExpr, err := a.resolver.ResolveExpr(expr, scope) if err != nil { - meta := expr.Meta.(core.Meta) //nolint:forcetypeassert + meta := expr.Meta //nolint:forcetypeassert return ts.Expr{}, &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), - Meta: &meta, + Message: err.Error(), + Meta: &meta, } } return resolvedExpr, nil @@ -62,8 +58,7 @@ func (a Analyzer) analyzeTypeParams( resolvedParams, _, err := a.resolver.ResolveParams(params, scope) if err != nil { return nil, &compiler.Error{ - Message: err.Error(), - Location: scope.Location(), + Message: err.Error(), } } return resolvedParams, nil From 90b669de3fc8f16b6672f6c45d9f4b403395d88a Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Sat, 7 Dec 2024 05:03:40 +0500 Subject: [PATCH 13/28] fix(di): bump --- docs/book/program_structure.md | 8 ++++---- e2e/interface_with_imports/neva.yml | 2 +- examples/neva.yml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/book/program_structure.md b/docs/book/program_structure.md index 2b61f673..30e61a2c 100644 --- a/docs/book/program_structure.md +++ b/docs/book/program_structure.md @@ -43,7 +43,7 @@ neva: 0.28.2 deps: github.com/nevalang/x: path: github.com/nevalang/x - version: 0.0.14 + version: 0.0.15 ``` 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: @@ -55,7 +55,7 @@ neva: 0.28.2 deps: github.com/nevalang/x@0-0-12: path: github.com/nevalang/x - version: 0.0.14 + version: 0.0.15 github.com/nevalang/x@0-0-11: path: github.com/nevalang/x version: 0.0.11 @@ -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.15 ``` ### Entry Module @@ -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.15 ``` Then when you `import { github.com/nevalang/x }` compiler will know exactly path and version of the module you are referring to. diff --git a/e2e/interface_with_imports/neva.yml b/e2e/interface_with_imports/neva.yml index d3c1a873..33600ebb 100644 --- a/e2e/interface_with_imports/neva.yml +++ b/e2e/interface_with_imports/neva.yml @@ -2,4 +2,4 @@ neva: 0.28.2 deps: github.com/nevalang/x: path: github.com/nevalang/x - version: 0.0.14 + version: 0.0.15 diff --git a/examples/neva.yml b/examples/neva.yml index d3c1a873..33600ebb 100644 --- a/examples/neva.yml +++ b/examples/neva.yml @@ -2,4 +2,4 @@ neva: 0.28.2 deps: github.com/nevalang/x: path: github.com/nevalang/x - version: 0.0.14 + version: 0.0.15 From d68c90f3c4fbd6973fc9dede24ba92f146fd514c Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Sat, 7 Dec 2024 16:44:38 +0500 Subject: [PATCH 14/28] fix(examples,e2e:interfaces): anonymous single-ports --- .gitignore | 1 + e2e/interface_anonymous/main/main.neva | 14 +++++++------- e2e/interface_verbose/main/main.neva | 18 +++++++++--------- e2e/interface_with_imports/main/main.neva | 16 ++++++++-------- examples/interfaces/main.neva | 16 ++++++++-------- 5 files changed, 33 insertions(+), 32 deletions(-) diff --git a/.gitignore b/.gitignore index 847f07c6..3ea0f1a2 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,4 @@ vendor tmp tmp.md todo.md +docker-compose.yml \ No newline at end of file diff --git a/e2e/interface_anonymous/main/main.neva b/e2e/interface_anonymous/main/main.neva index f51f7459..0e30f9e7 100644 --- a/e2e/interface_anonymous/main/main.neva +++ b/e2e/interface_anonymous/main/main.neva @@ -1,17 +1,17 @@ import { fmt } -interface IPrinter(data T) (sig T) - def Main(start any) (stop any) { - Secondflow { fmt.Println } + second_flow Secondflow {fmt.Println} --- - :start -> secondflow:msg - secondflow:msg -> :stop + :start -> second_flow:msg + second_flow:msg -> :stop } -def Secondflow (msg) (msg) { +def Secondflow (msg any) (msg any) { IPrinter --- :msg -> iPrinter:data iPrinter:sig -> :msg -} \ No newline at end of file +} + +interface IPrinter(T) (T) diff --git a/e2e/interface_verbose/main/main.neva b/e2e/interface_verbose/main/main.neva index f993fe15..d90b85d5 100644 --- a/e2e/interface_verbose/main/main.neva +++ b/e2e/interface_verbose/main/main.neva @@ -1,19 +1,19 @@ import { fmt } -interface IPrinter(data T) (sig T) - def Main(start any) (stop any) { - Secondflow { - depNode fmt.Println + second_flow Secondflow { + dep_node fmt.Println } --- - :start -> secondflow:msg - secondflow:msg -> :stop + :start -> second_flow:msg + second_flow:msg -> :stop } def Secondflow (msg any) (msg any) { - depNode IPrinter + dep_node IPrinter --- - :msg -> depNode:data - depNode:sig -> :msg + :msg -> dep_node:data + dep_node:sig -> :msg } + +interface IPrinter(T) (T) diff --git a/e2e/interface_with_imports/main/main.neva b/e2e/interface_with_imports/main/main.neva index 95d756e5..866bb741 100644 --- a/e2e/interface_with_imports/main/main.neva +++ b/e2e/interface_with_imports/main/main.neva @@ -1,17 +1,17 @@ import { github.com/nevalang/x:main } -interface IPrinter(data T) (sig T) - def Main(start any) (stop any) { - Secondflow {main.Println} + second_flow Secondflow{main.Println} --- - :start -> secondflow:msg - secondflow:msg -> :stop + :start -> second_flow:msg + second_flow:msg -> :stop } def Secondflow (msg any) (msg any) { - IPrinter + printer IPrinter --- - :msg -> iPrinter:data - iPrinter:sig -> :msg + :msg -> printer:data + printer:sig -> :msg } + +interface IPrinter(T) (T) diff --git a/examples/interfaces/main.neva b/examples/interfaces/main.neva index 5a5fb8b6..84c9e7f9 100644 --- a/examples/interfaces/main.neva +++ b/examples/interfaces/main.neva @@ -1,15 +1,15 @@ import { fmt } def Main(start any) (stop any) { - WithDep { fmt.Println } + wrapper Wrapper{fmt.Println} --- - :start -> withDep -> :stop + :start -> wrapper -> :stop } -interface IPrinter(data T) (sig T) - -def WithDep (msg any) (msg any) { - IPrinter +def Wrapper(msg any) (msg any) { + printer IPrinter --- - :msg -> iPrinter -> :msg -} \ No newline at end of file + :msg -> printer -> :msg +} + +interface IPrinter(T) (T) From b9773ee6c77c65e9789035c8887d5766e48a379c Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Sat, 7 Dec 2024 17:11:24 +0500 Subject: [PATCH 15/28] feat(deps): nevalang/x to 0016 --- docs/book/program_structure.md | 8 ++++---- e2e/interface_with_imports/neva.yml | 2 +- examples/neva.yml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/book/program_structure.md b/docs/book/program_structure.md index 30e61a2c..f0054159 100644 --- a/docs/book/program_structure.md +++ b/docs/book/program_structure.md @@ -43,7 +43,7 @@ neva: 0.28.2 deps: github.com/nevalang/x: path: github.com/nevalang/x - version: 0.0.15 + 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: @@ -55,7 +55,7 @@ neva: 0.28.2 deps: github.com/nevalang/x@0-0-12: path: github.com/nevalang/x - version: 0.0.15 + version: 0.0.16 github.com/nevalang/x@0-0-11: path: github.com/nevalang/x version: 0.0.11 @@ -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.15 +version: 0.0.16 ``` ### Entry Module @@ -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.15 + 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. diff --git a/e2e/interface_with_imports/neva.yml b/e2e/interface_with_imports/neva.yml index 33600ebb..23a78e8a 100644 --- a/e2e/interface_with_imports/neva.yml +++ b/e2e/interface_with_imports/neva.yml @@ -2,4 +2,4 @@ neva: 0.28.2 deps: github.com/nevalang/x: path: github.com/nevalang/x - version: 0.0.15 + version: 0.0.16 diff --git a/examples/neva.yml b/examples/neva.yml index 33600ebb..23a78e8a 100644 --- a/examples/neva.yml +++ b/examples/neva.yml @@ -2,4 +2,4 @@ neva: 0.28.2 deps: github.com/nevalang/x: path: github.com/nevalang/x - version: 0.0.15 + version: 0.0.16 From 8aa1e8e21108c61fef32d527e07cf26b96b1d757 Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Sat, 7 Dec 2024 20:45:40 +0500 Subject: [PATCH 16/28] refactor(compiler): move graphReduction to IR package, move its call from irgen to golang backend --- internal/compiler/backend/golang/backend.go | 14 ++++--- .../compiler/backend/golang/funcmap_test.go | 2 +- .../compiler/{irgen => ir}/graph_reduction.go | 22 +++++------ .../{irgen => ir}/graph_reduction_test.go | 37 +++++++++---------- internal/compiler/irgen/irgen.go | 6 +-- internal/compiler/sourcecode/scope.go | 2 +- 6 files changed, 38 insertions(+), 45 deletions(-) rename internal/compiler/{irgen => ir}/graph_reduction.go (70%) rename internal/compiler/{irgen => ir}/graph_reduction_test.go (74%) diff --git a/internal/compiler/backend/golang/backend.go b/internal/compiler/backend/golang/backend.go index c30140c5..e783476e 100644 --- a/internal/compiler/backend/golang/backend.go +++ b/internal/compiler/backend/golang/backend.go @@ -23,9 +23,11 @@ var ( ) func (b Backend) Emit(dst string, prog *ir.Program, trace bool) error { - addrToChanVar, chanVarNames := b.getPortChansMap(prog.Connections) + // graph must not contain intermediate connections to be supported by runtime + prog.Connections = ir.GraphReduction(prog.Connections) - funcCalls, err := b.getFuncCalls(prog.Funcs, addrToChanVar) + addrToChanVar, chanVarNames := b.buildPortChanMap(prog.Connections) + funcCalls, err := b.buildFuncCalls(prog.Funcs, addrToChanVar) if err != nil { return err } @@ -46,7 +48,7 @@ func (b Backend) Emit(dst string, prog *ir.Program, trace bool) error { return err } - data := templateData{ + tplData := templateData{ CompilerVersion: pkg.Version, ChanVarNames: chanVarNames, FuncCalls: funcCalls, @@ -54,7 +56,7 @@ func (b Backend) Emit(dst string, prog *ir.Program, trace bool) error { } var buf bytes.Buffer - if err := tmpl.Execute(&buf, data); err != nil { + if err := tmpl.Execute(&buf, tplData); err != nil { return errors.Join(ErrExecTmpl, err) } @@ -69,7 +71,7 @@ func (b Backend) Emit(dst string, prog *ir.Program, trace bool) error { return compiler.SaveFilesToDir(dst, files) } -func (b Backend) getFuncCalls( +func (b Backend) buildFuncCalls( funcs []ir.FuncCall, addrToChanVar map[ir.PortAddr]string, ) ([]templateFuncCall, error) { @@ -278,7 +280,7 @@ func (b Backend) insertRuntimeFiles(files map[string][]byte) error { return nil } -func (b Backend) getPortChansMap(connections map[ir.PortAddr]ir.PortAddr) (map[ir.PortAddr]string, []string) { +func (b Backend) buildPortChanMap(connections map[ir.PortAddr]ir.PortAddr) (map[ir.PortAddr]string, []string) { portsCount := len(connections) * 2 varNames := make([]string, 0, portsCount) addrToChanVar := make(map[ir.PortAddr]string, portsCount) diff --git a/internal/compiler/backend/golang/funcmap_test.go b/internal/compiler/backend/golang/funcmap_test.go index 14cd3abf..330795a8 100644 --- a/internal/compiler/backend/golang/funcmap_test.go +++ b/internal/compiler/backend/golang/funcmap_test.go @@ -71,7 +71,7 @@ func TestGetPortChansMap(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - result, _ := b.getPortChansMap(tt.connections) + result, _ := b.buildPortChanMap(tt.connections) assert.Equal(t, tt.expectedMap, result) }) } diff --git a/internal/compiler/irgen/graph_reduction.go b/internal/compiler/ir/graph_reduction.go similarity index 70% rename from internal/compiler/irgen/graph_reduction.go rename to internal/compiler/ir/graph_reduction.go index 8b446896..81032dc4 100644 --- a/internal/compiler/irgen/graph_reduction.go +++ b/internal/compiler/ir/graph_reduction.go @@ -1,13 +1,11 @@ -package irgen +package ir -import "github.com/nevalang/neva/internal/compiler/ir" - -// reduceFinalGraph transforms program to a state where it doesn't have intermediate connections. -func (Generator) reduceFinalGraph(connections map[ir.PortAddr]ir.PortAddr) map[ir.PortAddr]ir.PortAddr { - intermediatePorts := map[ir.PortAddr]struct{}{} +// GraphReduction removes intermediate connections and returns reduced graph. +func GraphReduction(connections map[PortAddr]PortAddr) map[PortAddr]PortAddr { + intermediatePorts := map[PortAddr]struct{}{} withoutIntermediateReceivers := make( - map[ir.PortAddr]ir.PortAddr, + map[PortAddr]PortAddr, len(connections), ) @@ -23,7 +21,7 @@ func (Generator) reduceFinalGraph(connections map[ir.PortAddr]ir.PortAddr) map[i // second pass: remove connections with intermediate senders result := make( - map[ir.PortAddr]ir.PortAddr, + map[PortAddr]PortAddr, len(withoutIntermediateReceivers), ) for sender, receiver := range withoutIntermediateReceivers { @@ -38,10 +36,10 @@ func (Generator) reduceFinalGraph(connections map[ir.PortAddr]ir.PortAddr) map[i // getFinalReceiver returns the final receiver for a given port address. // It also returns true if the given port address was intermediate, false otherwise. func getFinalReceiver( - receiver ir.PortAddr, - connections map[ir.PortAddr]ir.PortAddr, -) (final ir.PortAddr, intermediate bool) { - visited := make(map[ir.PortAddr]struct{}) + receiver PortAddr, + connections map[PortAddr]PortAddr, +) (final PortAddr, intermediate bool) { + visited := make(map[PortAddr]struct{}) current := receiver for { visited[current] = struct{}{} diff --git a/internal/compiler/irgen/graph_reduction_test.go b/internal/compiler/ir/graph_reduction_test.go similarity index 74% rename from internal/compiler/irgen/graph_reduction_test.go rename to internal/compiler/ir/graph_reduction_test.go index 5c9a0d18..1f81e79c 100644 --- a/internal/compiler/irgen/graph_reduction_test.go +++ b/internal/compiler/ir/graph_reduction_test.go @@ -1,53 +1,52 @@ -package irgen +package ir import ( "testing" - "github.com/nevalang/neva/internal/compiler/ir" "github.com/stretchr/testify/assert" ) -func TestReduceFinalGraph(t *testing.T) { +func Test_GraphReduction(t *testing.T) { tests := []struct { name string - input map[ir.PortAddr]ir.PortAddr - expected map[ir.PortAddr]ir.PortAddr + input map[PortAddr]PortAddr + expected map[PortAddr]PortAddr }{ { name: "simple_chain_reduction", // a:foo -> b:bar; b:bar -> c:baz - input: map[ir.PortAddr]ir.PortAddr{ + input: map[PortAddr]PortAddr{ {Path: "a", Port: "foo"}: {Path: "b", Port: "bar"}, {Path: "b", Port: "bar"}: {Path: "c", Port: "baz"}, }, // a:foo -> c:baz - expected: map[ir.PortAddr]ir.PortAddr{ + expected: map[PortAddr]PortAddr{ {Path: "a", Port: "foo"}: {Path: "c", Port: "baz"}, }, }, { name: "multiple_intermediate_nodes", // a:foo -> b:bar; b:bar -> c:baz; c:baz -> d:qux - input: map[ir.PortAddr]ir.PortAddr{ + input: map[PortAddr]PortAddr{ {Path: "a", Port: "foo"}: {Path: "b", Port: "bar"}, {Path: "b", Port: "bar"}: {Path: "c", Port: "baz"}, {Path: "c", Port: "baz"}: {Path: "d", Port: "qux"}, }, // a:foo -> d:qux - expected: map[ir.PortAddr]ir.PortAddr{ + expected: map[PortAddr]PortAddr{ {Path: "a", Port: "foo"}: {Path: "d", Port: "qux"}, }, }, { name: "branching_connections", // a:foo -> b:bar; b:bar -> c:baz; b:qux -> d:quux - input: map[ir.PortAddr]ir.PortAddr{ + input: map[PortAddr]PortAddr{ {Path: "a", Port: "foo"}: {Path: "b", Port: "bar"}, {Path: "b", Port: "bar"}: {Path: "c", Port: "baz"}, {Path: "b", Port: "qux"}: {Path: "d", Port: "quux"}, }, // a:foo -> c:baz; b:qux -> d:quux - expected: map[ir.PortAddr]ir.PortAddr{ + expected: map[PortAddr]PortAddr{ {Path: "a", Port: "foo"}: {Path: "c", Port: "baz"}, {Path: "b", Port: "qux"}: {Path: "d", Port: "quux"}, }, @@ -55,40 +54,38 @@ func TestReduceFinalGraph(t *testing.T) { { name: "cyclic_connections", // a:foo -> b:bar; b:bar -> c:baz; c:baz -> a:qux - input: map[ir.PortAddr]ir.PortAddr{ + input: map[PortAddr]PortAddr{ {Path: "a", Port: "foo"}: {Path: "b", Port: "bar"}, {Path: "b", Port: "bar"}: {Path: "c", Port: "baz"}, {Path: "c", Port: "baz"}: {Path: "a", Port: "qux"}, }, // a:foo -> a:qux - expected: map[ir.PortAddr]ir.PortAddr{ + expected: map[PortAddr]PortAddr{ {Path: "a", Port: "foo"}: {Path: "a", Port: "qux"}, }, }, { name: "array_ports", // a:foo[0] -> b:bar; b:bar -> c:baz[1] - input: map[ir.PortAddr]ir.PortAddr{ + input: map[PortAddr]PortAddr{ {Path: "a", Port: "foo", Idx: 0, IsArray: true}: {Path: "b", Port: "bar"}, {Path: "b", Port: "bar"}: {Path: "c", Port: "baz", Idx: 1, IsArray: true}, }, // a:foo[0] -> c:baz[1] - expected: map[ir.PortAddr]ir.PortAddr{ + expected: map[PortAddr]PortAddr{ {Path: "a", Port: "foo", Idx: 0, IsArray: true}: {Path: "c", Port: "baz", Idx: 1, IsArray: true}, // Direct connection from a:foo[0] to c:baz[1], preserving array indices }, }, { name: "empty_input", - input: map[ir.PortAddr]ir.PortAddr{}, - expected: map[ir.PortAddr]ir.PortAddr{}, + input: map[PortAddr]PortAddr{}, + expected: map[PortAddr]PortAddr{}, }, } - gen := Generator{} - for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - result := gen.reduceFinalGraph(tt.input) + result := GraphReduction(tt.input) assert.Equal(t, tt.expected, result) }) } diff --git a/internal/compiler/irgen/irgen.go b/internal/compiler/irgen/irgen.go index c63ca1f3..4fdb3f50 100644 --- a/internal/compiler/irgen/irgen.go +++ b/internal/compiler/irgen/irgen.go @@ -65,12 +65,8 @@ func (g Generator) Generate( return nil, fmt.Errorf("process node: %w", err) } - // graph reduction is not an optimization: - // it's a necessity for runtime not to have intermediate connections - reducedNet := g.reduceFinalGraph(result.Connections) - return &ir.Program{ - Connections: reducedNet, + Connections: result.Connections, Funcs: result.Funcs, }, nil } diff --git a/internal/compiler/sourcecode/scope.go b/internal/compiler/sourcecode/scope.go index 9a73f503..ddfd35b1 100644 --- a/internal/compiler/sourcecode/scope.go +++ b/internal/compiler/sourcecode/scope.go @@ -17,7 +17,7 @@ func NewScope(build Build, location core.Location) Scope { } } -// Scope is an object that provides access to program entities +// Scope is entity reference resolver type Scope struct { loc core.Location build Build From 63835654030254b30dd066e397feae7c89237480 Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Mon, 9 Dec 2024 00:59:50 +0500 Subject: [PATCH 17/28] wip(irgen): di drilling --- .../simplest_message_passing/bench_test.go | 27 ++ benchmarks/simplest_message_passing/main.neva | 5 + examples/reduce_list/main.neva | 8 +- internal/compiler/desugarer/desugarer.go | 2 + internal/compiler/desugarer/mocks_test.go | 30 ++ internal/compiler/desugarer/network.go | 58 +--- internal/compiler/irgen/irgen.go | 78 +++-- internal/compiler/irgen/network.go | 283 +++++++++++------- internal/compiler/sourcecode/scope.go | 73 ++++- std/builtin/streams.neva | 2 +- 10 files changed, 368 insertions(+), 198 deletions(-) create mode 100644 benchmarks/simplest_message_passing/bench_test.go create mode 100644 benchmarks/simplest_message_passing/main.neva diff --git a/benchmarks/simplest_message_passing/bench_test.go b/benchmarks/simplest_message_passing/bench_test.go new file mode 100644 index 00000000..9a9d876a --- /dev/null +++ b/benchmarks/simplest_message_passing/bench_test.go @@ -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()) + } +} diff --git a/benchmarks/simplest_message_passing/main.neva b/benchmarks/simplest_message_passing/main.neva new file mode 100644 index 00000000..9bb421c3 --- /dev/null +++ b/benchmarks/simplest_message_passing/main.neva @@ -0,0 +1,5 @@ +def Main(start any) (stop any) { + wait Wait + --- + :start -> 1..1000 -> wait -> :stop +} \ No newline at end of file diff --git a/examples/reduce_list/main.neva b/examples/reduce_list/main.neva index ae1c464b..5435ee6d 100644 --- a/examples/reduce_list/main.neva +++ b/examples/reduce_list/main.neva @@ -3,11 +3,11 @@ import { fmt } const lst list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] def Main(start any) (stop any) { - ListToStream - Reduce{Add} - fmt.Println + l2s ListToStream + reduce Reduce{Add} + println fmt.Println --- - :start -> $lst -> listToStream -> reduce:data + :start -> $lst -> l2s -> reduce:data 0 -> reduce:init reduce -> println -> :stop } diff --git a/internal/compiler/desugarer/desugarer.go b/internal/compiler/desugarer/desugarer.go index 5633c7b9..bf1df3ad 100644 --- a/internal/compiler/desugarer/desugarer.go +++ b/internal/compiler/desugarer/desugarer.go @@ -120,6 +120,8 @@ type Scope interface { Entity(ref core.EntityRef) (src.Entity, core.Location, error) Relocate(location core.Location) src.Scope Location() *core.Location + GetFirstInportName(nodes map[string]src.Node, portAddr src.PortAddr) (string, error) + GetFirstOutportName(nodes map[string]src.Node, portAddr src.PortAddr) (string, error) } func (d *Desugarer) desugarPkg(pkg src.Package, scope Scope) (src.Package, error) { diff --git a/internal/compiler/desugarer/mocks_test.go b/internal/compiler/desugarer/mocks_test.go index 50a939b7..58116e5c 100644 --- a/internal/compiler/desugarer/mocks_test.go +++ b/internal/compiler/desugarer/mocks_test.go @@ -51,6 +51,36 @@ func (mr *MockScopeMockRecorder) Entity(ref interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Entity", reflect.TypeOf((*MockScope)(nil).Entity), ref) } +// GetFirstInportName mocks base method. +func (m *MockScope) GetFirstInportName(nodes map[string]sourcecode.Node, portAddr sourcecode.PortAddr) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetFirstInportName", nodes, portAddr) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetFirstInportName indicates an expected call of GetFirstInportName. +func (mr *MockScopeMockRecorder) GetFirstInportName(nodes, portAddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFirstInportName", reflect.TypeOf((*MockScope)(nil).GetFirstInportName), nodes, portAddr) +} + +// GetFirstOutportName mocks base method. +func (m *MockScope) GetFirstOutportName(nodes map[string]sourcecode.Node, portAddr sourcecode.PortAddr) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetFirstOutportName", nodes, portAddr) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetFirstOutportName indicates an expected call of GetFirstOutportName. +func (mr *MockScopeMockRecorder) GetFirstOutportName(nodes, portAddr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFirstOutportName", reflect.TypeOf((*MockScope)(nil).GetFirstOutportName), nodes, portAddr) +} + // Location mocks base method. func (m *MockScope) Location() *core.Location { m.ctrl.T.Helper() diff --git a/internal/compiler/desugarer/network.go b/internal/compiler/desugarer/network.go index 3cdb0540..801589e8 100644 --- a/internal/compiler/desugarer/network.go +++ b/internal/compiler/desugarer/network.go @@ -1,7 +1,6 @@ package desugarer import ( - "errors" "fmt" "github.com/nevalang/neva/internal/compiler" @@ -230,11 +229,13 @@ func (d *Desugarer) desugarSingleReceiver( }, nil } - firstInportName, err := getFirstInportName(scope, nodes, *receiver.PortAddr) + firstInportName, err := scope.GetFirstInportName(nodes, *receiver.PortAddr) if err != nil { return desugarReceiverResult{}, fmt.Errorf("get first inport name: %w", err) } + // if node is interface with anonymous port, port-addr will remain empty string + // to be later desugared at irgen step, because it's not possible to do here return desugarReceiverResult{ replace: src.Connection{ Normal: &src.NormalConnection{ @@ -414,7 +415,7 @@ func (d *Desugarer) desugarChainedConnection( chainHeadPort = chainHead.PortAddr.Port if chainHeadPort == "" { var err error - chainHeadPort, err = getFirstInportName(scope, nodes, *chainHead.PortAddr) + chainHeadPort, err = scope.GetFirstInportName(nodes, *chainHead.PortAddr) if err != nil { return desugarConnectionResult{}, fmt.Errorf("get first inport name: %w", err) } @@ -632,7 +633,7 @@ func (d *Desugarer) desugarSingleSender( if sender.PortAddr != nil { portName := sender.PortAddr.Port if sender.PortAddr.Port == "" { - firstOutportName, err := getFirstOutportName(scope, nodes, *sender.PortAddr) + firstOutportName, err := scope.GetFirstOutportName(nodes, *sender.PortAddr) if err != nil { return desugarSenderResult{}, fmt.Errorf("get first outport name: %w", err) } @@ -652,6 +653,8 @@ func (d *Desugarer) desugarSingleSender( sender.PortAddr.Node, portName, ) + // if node is interface with anonymous port, port-addr will remain empty string + // to be later desugared at irgen step, because it's not possible to do here return desugarSenderResult{ replace: src.Connection{Normal: &normConn}, insert: nil, @@ -864,53 +867,6 @@ func (d *Desugarer) getConstTypeByRef(ref core.EntityRef, scope Scope) (ts.Expr, return entity.Const.TypeExpr, nil } -func getNodeIOByPortAddr( - scope Scope, - nodes map[string]src.Node, - portAddr *src.PortAddr, -) (src.IO, error) { - node, ok := nodes[portAddr.Node] - if !ok { - return src.IO{}, fmt.Errorf("node '%s' not found", portAddr.Node) - } - - entity, _, err := scope.Entity(node.EntityRef) - if err != nil { - return src.IO{}, fmt.Errorf("get entity: %w", err) - } - - var iface src.Interface - if entity.Kind == src.InterfaceEntity { - iface = entity.Interface - } else { - iface = entity.Component.Interface - } - - return iface.IO, nil -} - -func getFirstInportName(scope Scope, nodes map[string]src.Node, portAddr src.PortAddr) (string, error) { - io, err := getNodeIOByPortAddr(scope, nodes, &portAddr) - if err != nil { - return "", err - } - for inport := range io.In { - return inport, nil - } - return "", errors.New("first inport not found") -} - -func getFirstOutportName(scope Scope, nodes map[string]src.Node, portAddr src.PortAddr) (string, error) { - io, err := getNodeIOByPortAddr(scope, nodes, &portAddr) - if err != nil { - return "", err - } - for outport := range io.Out { - return outport, nil - } - return "", errors.New("first outport not found") -} - type desugarFanOutResult struct { replace src.Connection // original sender -> fanOut receiver insert []src.Connection // fanOut sender -> original receivers diff --git a/internal/compiler/irgen/irgen.go b/internal/compiler/irgen/irgen.go index 4fdb3f50..57a31073 100644 --- a/internal/compiler/irgen/irgen.go +++ b/internal/compiler/irgen/irgen.go @@ -61,9 +61,7 @@ func (g Generator) Generate( }, } - if err := g.processNode(rootNodeCtx, scope, result); err != nil { - return nil, fmt.Errorf("process node: %w", err) - } + g.processNode(rootNodeCtx, scope, result) return &ir.Program{ Connections: result.Connections, @@ -75,26 +73,25 @@ func (g Generator) processNode( nodeCtx nodeContext, scope src.Scope, result *ir.Program, -) error { +) { entity, location, err := scope.Entity(nodeCtx.node.EntityRef) if err != nil { - return fmt.Errorf("get entity: %w", err) + panic(err) } component := entity.Component - inportAddrs := g.insertAndReturnInports(nodeCtx) // for inports we only use parent context because all inports are used outportAddrs := g.insertAndReturnOutports(nodeCtx) // for outports we use both parent context and component's interface runtimeFuncRef, err := g.getFuncRef(component, nodeCtx.node.TypeArgs) if err != nil { - return fmt.Errorf("get func ref: %w", err) + panic(err) } if runtimeFuncRef != "" { cfgMsg, err := getConfigMsg(nodeCtx.node, scope) if err != nil { - return fmt.Errorf("get config msg: %w", err) + panic(err) } result.Funcs = append(result.Funcs, ir.FuncCall{ Ref: runtimeFuncRef, @@ -104,27 +101,26 @@ func (g Generator) processNode( }, Msg: cfgMsg, }) - return nil + return } - newScope := scope.Relocate(location) // only use new location if that's not builtin - // We use network as a source of true about how subnodes ports instead subnodes interface definitions. // We cannot rely on them because there's no information about how many array slots are used (in case of array ports). // On the other hand, we believe network has everything we need because program' correctness is verified by analyzer. subnodesPortsUsage, err := g.processNetwork( component.Net, + &scope, nodeCtx, result, ) if err != nil { - return fmt.Errorf("process network: %w", err) + panic(err) } - for nodeName, node := range component.Nodes { - nodePortsUsage, ok := subnodesPortsUsage[nodeName] + for subnodeName, subnode := range component.Nodes { + nodePortsUsage, ok := subnodesPortsUsage[subnodeName] if !ok { - return fmt.Errorf("node usage not found: %v", nodeName) + panic(fmt.Errorf("node usage not found: %v", subnodeName)) } // TODO e2e test @@ -134,36 +130,60 @@ func (g Generator) processNode( // Parent.handler is not interface, but its component has interface // It needs our DI nodes, so we merge our DI with node's DI if len(nodeCtx.node.DIArgs) > 0 { - if node.DIArgs == nil { - node.DIArgs = make(map[string]src.Node) + if subnode.DIArgs == nil { + subnode.DIArgs = make(map[string]src.Node) } for k, ourDIarg := range nodeCtx.node.DIArgs { - if _, exists := node.DIArgs[k]; !exists { - node.DIArgs[k] = ourDIarg + // FIXME HOC with drilled di arg can't resolve ref to it + // because it resolves it with its own location + // rather than with the location, where drilled DI arg was first passed + + // FIXME handle case when DI args drilled anonymously + // e.g. when we pass Filter{Predicate} so Split{Predicate} works + // and predicate is k="" figure out by desugarer + // to do so, we need to take first Split's DI param name and use it instead of k + // Analyzer probably must check where it's possible to use anonymous DI args and where not + // without explicit names we would have to traverse all component tree down to the leaf + // that uses actual dependency, to get its DI name + // so anonymous DI args are only possible without DI drilling. + + // if sub-node doesn't have DI arg, we just add it + existing, exists := subnode.DIArgs[k] + if !exists { + subnode.DIArgs[k] = ourDIarg + continue + } + + // if sub-node has DI arg, we check if it's interface + kind, err := scope.GetEntityKind(existing.EntityRef) + if err != nil { + panic(err) + } + + // if it's interface, we replace it with our DI arg + // that's how we can drill DI arguments down to composite components + if kind == src.InterfaceEntity { + subnode.DIArgs[k] = ourDIarg } } } subNodeCtx := nodeContext{ - path: append(nodeCtx.path, nodeName), + path: append(nodeCtx.path, subnodeName), portsUsage: nodePortsUsage, - node: node, + node: subnode, } var scopeToUse src.Scope - if injectedNode, isDINode := nodeCtx.node.DIArgs[nodeName]; isDINode { - subNodeCtx.node = injectedNode + if injectedSubnode, isDISubnode := nodeCtx.node.DIArgs[subnodeName]; isDISubnode { + subNodeCtx.node = injectedSubnode scopeToUse = scope } else { - scopeToUse = newScope + scopeToUse = scope.Relocate(location) } - if err := g.processNode(subNodeCtx, scopeToUse, result); err != nil { - return fmt.Errorf("process node: %w", err) - } + g.processNode(subNodeCtx, scopeToUse, result) } - - return nil } func (Generator) insertAndReturnInports(nodeCtx nodeContext) []ir.PortAddr { diff --git a/internal/compiler/irgen/network.go b/internal/compiler/irgen/network.go index af67b6da..f82d30e0 100644 --- a/internal/compiler/irgen/network.go +++ b/internal/compiler/irgen/network.go @@ -1,7 +1,6 @@ package irgen import ( - "fmt" "sort" "strings" @@ -9,173 +8,219 @@ import ( src "github.com/nevalang/neva/internal/compiler/sourcecode" ) -// processNetwork -// 1) inserts network connections -// 2) returns metadata about how subnodes are used by this network +// processNetwork inserts connections to result and returns metadata about the network. func (g Generator) processNetwork( conns []src.Connection, + scope *src.Scope, nodeCtx nodeContext, result *ir.Program, ) (map[string]portsUsage, error) { nodesPortsUsage := map[string]portsUsage{} for _, conn := range conns { - // here's how we handle array-bypass connections: - // sender is always component's inport - // based on that, we can set receiver's inport slots - // equal to slots of our own inport if conn.ArrayBypass != nil { - arrBypassSender := conn.ArrayBypass.SenderOutport - arrBypassReceiver := conn.ArrayBypass.ReceiverInport - - if _, ok := nodesPortsUsage[arrBypassReceiver.Node]; !ok { - nodesPortsUsage[arrBypassReceiver.Node] = portsUsage{ - in: map[relPortAddr]struct{}{}, - out: map[relPortAddr]struct{}{}, - } - } - - var slotIdx uint8 = 0 - for usageAddr := range nodeCtx.portsUsage.in { - if usageAddr.Port != arrBypassSender.Port { // we only care about the port we're bypassing - continue - } - - slotIdxCopy := slotIdx // fix of "Using the variable on range scope" issue - - addr := relPortAddr{Port: arrBypassReceiver.Port, Idx: &slotIdxCopy} // TODO check if pointer is ok to use here - nodesPortsUsage[arrBypassReceiver.Node].in[addr] = struct{}{} - - irSenderSlot := ir.PortAddr{ - Path: joinNodePath(nodeCtx.path, arrBypassSender.Node), - Port: arrBypassSender.Port, - Idx: slotIdxCopy, - IsArray: true, - } - - irReceiverSlot := ir.PortAddr{ - Path: joinNodePath(nodeCtx.path, arrBypassReceiver.Node) + "/in", - Port: arrBypassReceiver.Port, - Idx: slotIdxCopy, - IsArray: true, - } - - result.Connections[irSenderSlot] = irReceiverSlot - - slotIdx++ - } - + g.processArrayBypassConnection( + conn, + nodesPortsUsage, + nodeCtx, + result, + ) continue } - if len(conn.Normal.Senders) != 1 { - return nil, fmt.Errorf( - "expected exactly one sender side in desugared network, got %v", - len(conn.Normal.Senders), - ) + if len(conn.Normal.Senders) != 1 || len(conn.Normal.Receivers) != 1 { + panic("not 1-1 connection found after desugaring") } - sender := conn.Normal.Senders[0] - - irSenderSidePortAddr, err := g.processSenderSide( + g.processNormalConnection( nodeCtx, - sender, + scope, + conn, nodesPortsUsage, + result, ) - if err != nil { - return nil, fmt.Errorf("process sender side: %w", err) + } + + return nodesPortsUsage, nil +} + +func (Generator) processArrayBypassConnection( + conn src.Connection, + nodesPortsUsage map[string]portsUsage, + nodeCtx nodeContext, + result *ir.Program, +) { + // here's how we handle array-bypass connections: + // sender is always component's inport + // based on that, we can set receiver's inport slots + // equal to slots of our own inport + + arrBypassSender := conn.ArrayBypass.SenderOutport + arrBypassReceiver := conn.ArrayBypass.ReceiverInport + + if _, ok := nodesPortsUsage[arrBypassReceiver.Node]; !ok { + nodesPortsUsage[arrBypassReceiver.Node] = portsUsage{ + in: map[relPortAddr]struct{}{}, + out: map[relPortAddr]struct{}{}, } + } - for _, receiverSide := range conn.Normal.Receivers { - receiverSideIR := g.mapReceiverSide(nodeCtx.path, receiverSide) + var slotIdx uint8 = 0 + for usageAddr := range nodeCtx.portsUsage.in { + if usageAddr.Port != arrBypassSender.Port { + continue + } - result.Connections[irSenderSidePortAddr] = receiverSideIR + slotIdxCopy := slotIdx - // same receiver can be used by multiple senders so we only add it once - if _, ok := nodesPortsUsage[receiverSide.PortAddr.Node]; !ok { - nodesPortsUsage[receiverSide.PortAddr.Node] = portsUsage{ - in: map[relPortAddr]struct{}{}, - out: map[relPortAddr]struct{}{}, - } - } + addr := relPortAddr{Port: arrBypassReceiver.Port, Idx: &slotIdxCopy} + nodesPortsUsage[arrBypassReceiver.Node].in[addr] = struct{}{} - receiverNode := receiverSide.PortAddr.Node - receiverPortAddr := relPortAddr{ - Port: receiverSide.PortAddr.Port, - Idx: receiverSide.PortAddr.Idx, - } + irSenderSlot := ir.PortAddr{ + Path: joinNodePath(nodeCtx.path, arrBypassSender.Node), + Port: arrBypassSender.Port, + Idx: slotIdxCopy, + IsArray: true, + } - nodesPortsUsage[receiverNode].in[receiverPortAddr] = struct{}{} + irReceiverSlot := ir.PortAddr{ + Path: joinNodePath(nodeCtx.path, arrBypassReceiver.Node) + "/in", + Port: arrBypassReceiver.Port, + Idx: slotIdxCopy, + IsArray: true, } + + result.Connections[irSenderSlot] = irReceiverSlot + + slotIdx++ } +} - return nodesPortsUsage, nil +func (g Generator) processNormalConnection( + nodeCtx nodeContext, + scope *src.Scope, + conn src.Connection, + nodesPortsUsage map[string]portsUsage, + result *ir.Program, +) { + irSenderSidePortAddr := g.processSender( + nodeCtx, + scope, + conn.Normal.Senders[0], + nodesPortsUsage, + ) + irReceiverPortAddr := g.processReceiver( + nodeCtx, + scope, + conn.Normal.Receivers[0], + nodesPortsUsage, + ) + result.Connections[irSenderSidePortAddr] = irReceiverPortAddr } -func (g Generator) processSenderSide( +func (g Generator) processSender( nodeCtx nodeContext, - senderSide src.ConnectionSender, - result map[string]portsUsage, -) (ir.PortAddr, error) { + scope *src.Scope, + sender src.ConnectionSender, + nodesUsage map[string]portsUsage, +) ir.PortAddr { // there could be many connections with the same sender but we must only add it once - if _, ok := result[senderSide.PortAddr.Node]; !ok { - result[senderSide.PortAddr.Node] = portsUsage{ + if _, ok := nodesUsage[sender.PortAddr.Node]; !ok { + nodesUsage[sender.PortAddr.Node] = portsUsage{ in: map[relPortAddr]struct{}{}, out: map[relPortAddr]struct{}{}, } } + // if sender node is dependency from DI and if port we are reffering to is an empty string + // we need to find depedency component and use its outport name + // this is techically desugaring at irgen level but it's impossible to desugare before + // because only irgen really builds nodes and passes DI args to them + depNode, isNodeDep := nodeCtx.node.DIArgs[sender.PortAddr.Node] + if isNodeDep && sender.PortAddr.Port == "" { + depComponent, err := scope.GetComponent(depNode.EntityRef) + if err != nil { + panic(err) + } + for outport := range depComponent.Interface.IO.Out { + sender.PortAddr.Port = outport + break + } + } + // insert outport usage - result[senderSide.PortAddr.Node].out[relPortAddr{ - Port: senderSide.PortAddr.Port, - Idx: senderSide.PortAddr.Idx, + nodesUsage[sender.PortAddr.Node].out[relPortAddr{ + Port: sender.PortAddr.Port, + Idx: sender.PortAddr.Idx, }] = struct{}{} + // create ir port addr irSenderPort := ir.PortAddr{ - Path: joinNodePath(nodeCtx.path, senderSide.PortAddr.Node), - Port: senderSide.PortAddr.Port, + Path: joinNodePath(nodeCtx.path, sender.PortAddr.Node), + Port: sender.PortAddr.Port, } - if senderSide.PortAddr.Idx != nil { + if sender.PortAddr.Idx != nil { irSenderPort.IsArray = true - irSenderPort.Idx = *senderSide.PortAddr.Idx + irSenderPort.Idx = *sender.PortAddr.Idx } - - if senderSide.PortAddr.Node != "in" { + if sender.PortAddr.Node != "in" { irSenderPort.Path += "/out" } - return irSenderPort, nil + return irSenderPort } -// this is very important because runtime function calls depends on this order. -func sortPortAddrs(addrs []ir.PortAddr) { - sort.Slice(addrs, func(i, j int) bool { - if addrs[i].Path != addrs[j].Path { - return addrs[i].Path < addrs[j].Path +// processReceiver maps src connection side to ir connection side 1-1 just making the port addr's path absolute +func (g Generator) processReceiver( + nodeCtx nodeContext, + scope *src.Scope, + receiver src.ConnectionReceiver, + nodesUsage map[string]portsUsage, +) ir.PortAddr { + // same receiver can be used by multiple senders so we only add it once + if _, ok := nodesUsage[receiver.PortAddr.Node]; !ok { + nodesUsage[receiver.PortAddr.Node] = portsUsage{ + in: map[relPortAddr]struct{}{}, + out: map[relPortAddr]struct{}{}, } - if addrs[i].Port != addrs[j].Port { - return addrs[i].Port < addrs[j].Port + } + + // if sender node is dependency from DI + depNode, ok := nodeCtx.node.DIArgs[receiver.PortAddr.Node] + // and if port we are reffering to is an empty string + if ok && receiver.PortAddr.Port == "" { + // we need to find depedency component and use its inport name + // this is techically desugaring at irgen level + // but it's impossible to desugare before, because only irgen really builds nodes + depComponent, err := scope.GetComponent(depNode.EntityRef) + if err != nil { + panic(err) } - if !addrs[i].IsArray { - return true + for inport := range depComponent.Interface.IO.In { + receiver.PortAddr.Port = inport + break } - return addrs[i].Idx < addrs[j].Idx - }) -} + } + + receiverNode := receiver.PortAddr.Node + receiverPortAddr := relPortAddr{ + Port: receiver.PortAddr.Port, + Idx: receiver.PortAddr.Idx, + } + + nodesUsage[receiverNode].in[receiverPortAddr] = struct{}{} -// mapReceiverSide maps src connection side to ir connection side 1-1 just making the port addr's path absolute -func (g Generator) mapReceiverSide(nodeCtxPath []string, side src.ConnectionReceiver) ir.PortAddr { result := ir.PortAddr{ - Path: joinNodePath(nodeCtxPath, side.PortAddr.Node), - Port: side.PortAddr.Port, + Path: joinNodePath(nodeCtx.path, receiver.PortAddr.Node), + Port: receiver.PortAddr.Port, } - if side.PortAddr.Idx != nil { + if receiver.PortAddr.Idx != nil { result.IsArray = true - result.Idx = *side.PortAddr.Idx + result.Idx = *receiver.PortAddr.Idx } // 'out' node is actually receiver but we don't want to have 'out/in' path - if side.PortAddr.Node != "out" { + if receiver.PortAddr.Node != "out" { result.Path += "/in" } @@ -188,3 +233,19 @@ func joinNodePath(nodePath []string, nodeName string) string { newPath = append(newPath, nodeName) return strings.Join(newPath, "/") } + +// this is very important because runtime function calls depends on this order. +func sortPortAddrs(addrs []ir.PortAddr) { + sort.Slice(addrs, func(i, j int) bool { + if addrs[i].Path != addrs[j].Path { + return addrs[i].Path < addrs[j].Path + } + if addrs[i].Port != addrs[j].Port { + return addrs[i].Port < addrs[j].Port + } + if !addrs[i].IsArray { + return true + } + return addrs[i].Idx < addrs[j].Idx + }) +} diff --git a/internal/compiler/sourcecode/scope.go b/internal/compiler/sourcecode/scope.go index ddfd35b1..c64e4afb 100644 --- a/internal/compiler/sourcecode/scope.go +++ b/internal/compiler/sourcecode/scope.go @@ -49,19 +49,34 @@ func (s Scope) IsTopType(expr ts.Expr) bool { // GetType returns type definition by reference func (s Scope) GetType(ref core.EntityRef) (ts.Def, ts.Scope, error) { - entity, location, err := s.Entity(ref) + entity, location, err := s.entity(ref) if err != nil { return ts.Def{}, nil, err } - return entity.Type, s.Relocate(location), nil } +func (s Scope) GetInterface(ref core.EntityRef) (Interface, error) { + entity, _, err := s.entity(ref) + if err != nil { + return Interface{}, err + } + return entity.Interface, nil +} + // Entity returns entity by reference func (s Scope) Entity(entityRef core.EntityRef) (Entity, core.Location, error) { return s.entity(entityRef) } +func (s Scope) GetComponent(entityRef core.EntityRef) (Component, error) { + entity, _, err := s.entity(entityRef) + if err != nil { + return Component{}, err + } + return entity.Component, nil +} + // entity is an alrogithm that resolves entity reference based on scope's location func (s Scope) entity(entityRef core.EntityRef) (Entity, core.Location, error) { curMod, ok := s.build.Modules[s.loc.ModRef] @@ -151,3 +166,57 @@ func (s Scope) entity(entityRef core.EntityRef) (Entity, core.Location, error) { Filename: fileName, }, nil } + +func (s Scope) getNodeIOByPortAddr( + nodes map[string]Node, + portAddr *PortAddr, +) (IO, error) { + node, ok := nodes[portAddr.Node] + if !ok { + return IO{}, fmt.Errorf("node '%s' not found", portAddr.Node) + } + + entity, _, err := s.Entity(node.EntityRef) + if err != nil { + return IO{}, fmt.Errorf("get entity: %w", err) + } + + var iface Interface + if entity.Kind == InterfaceEntity { + iface = entity.Interface + } else { + iface = entity.Component.Interface + } + + return iface.IO, nil +} + +func (s Scope) GetFirstInportName(nodes map[string]Node, portAddr PortAddr) (string, error) { + io, err := s.getNodeIOByPortAddr(nodes, &portAddr) + if err != nil { + return "", err + } + for inport := range io.In { + return inport, nil + } + return "", errors.New("first inport not found") +} + +func (s Scope) GetEntityKind(entityRef core.EntityRef) (EntityKind, error) { + entity, _, err := s.Entity(entityRef) + if err != nil { + return "", err + } + return entity.Kind, nil +} + +func (s Scope) GetFirstOutportName(nodes map[string]Node, portAddr PortAddr) (string, error) { + io, err := s.getNodeIOByPortAddr(nodes, &portAddr) + if err != nil { + return "", err + } + for outport := range io.Out { + return outport, nil + } + return "", errors.New("first outport not found") +} diff --git a/std/builtin/streams.neva b/std/builtin/streams.neva index 9e6019f7..5de1bb97 100644 --- a/std/builtin/streams.neva +++ b/std/builtin/streams.neva @@ -55,7 +55,7 @@ pub def Map(data stream) (res stream) { // --- Filter --- pub def Filter(data stream) (res stream) { - split Split{IPredicate} + split Split{IPredicate} s2l StreamToList l2s ListToStream --- From ffb79071b303fbde3e8a4c141858142f75c5b85d Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Tue, 10 Dec 2024 23:17:05 +0500 Subject: [PATCH 18/28] feat(lsp): fix bug when module found up to workspace and we see its problems --- .vscode/launch.json | 4 ++-- cmd/lsp/indexer/indexer.go | 36 ++++++++++++++++++++++++++---- cmd/lsp/server/general_messages.go | 1 + cmd/lsp/server/server.go | 21 ++++++++++++----- 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index c9612828..25109744 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,8 +7,8 @@ "request": "launch", "mode": "auto", "program": "${workspaceFolder}/cmd/neva", - "cwd": "${workspaceFolder}/examples", - "args": ["run", "--trace", "filter_list"] + "cwd": "${workspaceFolder}/e2e/filter_list", + "args": ["run", "--trace", "main"] }, { "name": "DEBUG CODEGEN", diff --git a/cmd/lsp/indexer/indexer.go b/cmd/lsp/indexer/indexer.go index c7bde73e..efccf141 100644 --- a/cmd/lsp/indexer/indexer.go +++ b/cmd/lsp/indexer/indexer.go @@ -2,6 +2,8 @@ package indexer import ( "context" + "path/filepath" + "strings" "github.com/nevalang/neva/internal/builder" "github.com/nevalang/neva/internal/compiler" @@ -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( diff --git a/cmd/lsp/server/general_messages.go b/cmd/lsp/server/general_messages.go index f45795d0..35806002 100644 --- a/cmd/lsp/server/general_messages.go +++ b/cmd/lsp/server/general_messages.go @@ -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{ diff --git a/cmd/lsp/server/server.go b/cmd/lsp/server/server.go index e949b3fe..d2352d17 100644 --- a/cmd/lsp/server/server.go +++ b/cmd/lsp/server/server.go @@ -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 { @@ -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.Meta.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 From dcc469d17e7d268cdea0c2d5676c63777a3f43b0 Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Tue, 10 Dec 2024 23:18:02 +0500 Subject: [PATCH 19/28] fix(cli): trim tailing / when `neva run` or `neva build` are executed --- internal/cli/build.go | 2 +- internal/cli/cli.go | 14 +++++++++----- internal/cli/run.go | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/internal/cli/build.go b/internal/cli/build.go index 8ec74f09..73f13f0d 100644 --- a/internal/cli/build.go +++ b/internal/cli/build.go @@ -43,7 +43,7 @@ func newBuildCmd( }, ArgsUsage: "Provide path to main package", Action: func(cliCtx *cli.Context) error { - mainPkg, err := getMainPkgFromArgs(cliCtx) + mainPkg, err := mainPkgPathFromArgs(cliCtx) if err != nil { return err } diff --git a/internal/cli/cli.go b/internal/cli/cli.go index 4f60ced7..afc1bbc3 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -93,13 +93,17 @@ func newGetCmd(workdir string, bldr builder.Builder) *cli.Command { } } -func getMainPkgFromArgs(cCtx *cli.Context) (string, error) { - firstArg := cCtx.Args().First() - dirFromArg := strings.TrimSuffix(firstArg, "/main.neva") - if filepath.Ext(dirFromArg) != "" { +func mainPkgPathFromArgs(cCtx *cli.Context) (string, error) { + arg := cCtx.Args().First() + + path := strings.TrimSuffix(arg, "main.neva") + path = strings.TrimSuffix(path, "/") + + if filepath.Ext(path) != "" { return "", errors.New( "Use path to directory with executable package, relative to module root", ) } - return dirFromArg, nil + + return path, nil } diff --git a/internal/cli/run.go b/internal/cli/run.go index 0c5978af..f619cc43 100644 --- a/internal/cli/run.go +++ b/internal/cli/run.go @@ -24,7 +24,7 @@ func newRunCmd(workdir string, nativec compiler.Compiler) *cli.Command { }, ArgsUsage: "Provide path to main package", Action: func(cliCtx *cli.Context) error { - mainPkg, err := getMainPkgFromArgs(cliCtx) + mainPkg, err := mainPkgPathFromArgs(cliCtx) if err != nil { return err } From b40fa5b22a6992e77b450b27ae2af441165ee79a Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Tue, 10 Dec 2024 23:20:34 +0500 Subject: [PATCH 20/28] fix(compiler): add missing path to fe result --- internal/compiler/compiler.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/internal/compiler/compiler.go b/internal/compiler/compiler.go index 9c5f4872..c9ae8d78 100644 --- a/internal/compiler/compiler.go +++ b/internal/compiler/compiler.go @@ -44,10 +44,11 @@ type FrontendResult struct { MainPkg string RawBuild RawBuild ParsedBuild sourcecode.Build + Path string } func (f Frontend) Process(ctx context.Context, main string) (FrontendResult, *Error) { - raw, root, err := f.builder.Build(ctx, main) + raw, moduleRoot, err := f.builder.Build(ctx, main) if err != nil { return FrontendResult{}, err } @@ -63,12 +64,13 @@ func (f Frontend) Process(ctx context.Context, main string) (FrontendResult, *Er } mainPkg := strings.TrimPrefix(main, "./") - mainPkg = strings.TrimPrefix(mainPkg, root+"/") + mainPkg = strings.TrimPrefix(mainPkg, moduleRoot+"/") return FrontendResult{ ParsedBuild: parsedBuild, RawBuild: raw, MainPkg: mainPkg, + Path: moduleRoot, }, nil } From 2a6e7922f4783dea301cf69ea976b563f0a32c0f Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Wed, 11 Dec 2024 22:58:36 +0500 Subject: [PATCH 21/28] refactor(std): port names --- docs/book/directives.md | 2 +- {examples => e2e}/filter_list/e2e_test.go | 2 ++ .../filter_list/main}/main.neva | 2 +- e2e/filter_list/neva.yml | 1 + e2e/hello_world_verbose/main/main.neva | 2 +- e2e/interface_anonymous/main/main.neva | 12 +++++----- e2e/interface_verbose/main/main.neva | 10 ++++---- e2e/interface_with_imports/main/main.neva | 10 ++++---- e2e/struct_builder_verbose/main/main.neva | 6 ++--- e2e/struct_builder_with_sugar/main/main.neva | 10 ++++---- .../main/main.neva | 6 ++--- examples/fib/main.neva | 23 +++++++++++++++++++ examples/interfaces/main.neva | 4 ++-- internal/runtime/funcs/del.go | 2 +- internal/runtime/funcs/new.go | 4 ++-- internal/runtime/funcs/new_v2.go | 2 +- internal/runtime/funcs/panic.go | 2 +- internal/runtime/funcs/struct_builder.go | 2 +- std/builtin/core.neva | 10 ++++---- std/builtin/streams.neva | 2 +- 20 files changed, 69 insertions(+), 45 deletions(-) rename {examples => e2e}/filter_list/e2e_test.go (95%) rename {examples/filter_list => e2e/filter_list/main}/main.neva (88%) create mode 100644 e2e/filter_list/neva.yml create mode 100644 examples/fib/main.neva diff --git a/docs/book/directives.md b/docs/book/directives.md index 76d4b2fd..2afe92fe 100644 --- a/docs/book/directives.md +++ b/docs/book/directives.md @@ -34,7 +34,7 @@ def Main(start any) (stop any) { lock Lock --- :start -> lock:sig - greeting:msg -> lock:data + greeting:res -> lock:data lock:data -> println:data println:res -> :stop } diff --git a/examples/filter_list/e2e_test.go b/e2e/filter_list/e2e_test.go similarity index 95% rename from examples/filter_list/e2e_test.go rename to e2e/filter_list/e2e_test.go index b18adc9b..80ed4992 100644 --- a/examples/filter_list/e2e_test.go +++ b/e2e/filter_list/e2e_test.go @@ -11,6 +11,8 @@ import ( ) func Test(t *testing.T) { + t.Skip("skipping for now") // TODO + err := os.Chdir("..") require.NoError(t, err) diff --git a/examples/filter_list/main.neva b/e2e/filter_list/main/main.neva similarity index 88% rename from examples/filter_list/main.neva rename to e2e/filter_list/main/main.neva index 80cd1ff9..dcbf0a5b 100644 --- a/examples/filter_list/main.neva +++ b/e2e/filter_list/main/main.neva @@ -4,7 +4,7 @@ const lst list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] def Main(start any) (stop any) { l2s ListToStream - filter_even Filter{Even} + filter_even Filter{predicate Even} for_print For{fmt.Println} wait Wait --- diff --git a/e2e/filter_list/neva.yml b/e2e/filter_list/neva.yml new file mode 100644 index 00000000..f25b3e9f --- /dev/null +++ b/e2e/filter_list/neva.yml @@ -0,0 +1 @@ +neva: 0.28.2 \ No newline at end of file diff --git a/e2e/hello_world_verbose/main/main.neva b/e2e/hello_world_verbose/main/main.neva index b90499cb..8122381d 100644 --- a/e2e/hello_world_verbose/main/main.neva +++ b/e2e/hello_world_verbose/main/main.neva @@ -11,7 +11,7 @@ def Main(start any) (stop any) { --- :start -> lock:sig - greeting:msg -> lock:data + greeting:res -> lock:data lock:data -> println:data println:res -> :stop } \ No newline at end of file diff --git a/e2e/interface_anonymous/main/main.neva b/e2e/interface_anonymous/main/main.neva index 0e30f9e7..a2040184 100644 --- a/e2e/interface_anonymous/main/main.neva +++ b/e2e/interface_anonymous/main/main.neva @@ -3,15 +3,15 @@ import { fmt } def Main(start any) (stop any) { second_flow Secondflow {fmt.Println} --- - :start -> second_flow:msg - second_flow:msg -> :stop + :start -> second_flow:data + second_flow:res -> :stop } -def Secondflow (msg any) (msg any) { - IPrinter +def Secondflow (data any) (res any) { + iPrinter IPrinter --- - :msg -> iPrinter:data - iPrinter:sig -> :msg + :data -> iPrinter:res + iPrinter:sig -> :res } interface IPrinter(T) (T) diff --git a/e2e/interface_verbose/main/main.neva b/e2e/interface_verbose/main/main.neva index d90b85d5..1cd1cfaf 100644 --- a/e2e/interface_verbose/main/main.neva +++ b/e2e/interface_verbose/main/main.neva @@ -5,15 +5,15 @@ def Main(start any) (stop any) { dep_node fmt.Println } --- - :start -> second_flow:msg - second_flow:msg -> :stop + :start -> second_flow:data + second_flow:res -> :stop } -def Secondflow (msg any) (msg any) { +def Secondflow (data any) (res any) { dep_node IPrinter --- - :msg -> dep_node:data - dep_node:sig -> :msg + :data -> dep_node:res + dep_node:sig -> :res } interface IPrinter(T) (T) diff --git a/e2e/interface_with_imports/main/main.neva b/e2e/interface_with_imports/main/main.neva index 866bb741..5fc5edd9 100644 --- a/e2e/interface_with_imports/main/main.neva +++ b/e2e/interface_with_imports/main/main.neva @@ -3,15 +3,15 @@ import { github.com/nevalang/x:main } def Main(start any) (stop any) { second_flow Secondflow{main.Println} --- - :start -> second_flow:msg - second_flow:msg -> :stop + :start -> second_flow:data + second_flow:res -> :stop } -def Secondflow (msg any) (msg any) { +def Secondflow (data any) (res any) { printer IPrinter --- - :msg -> printer:data - printer:sig -> :msg + :data -> printer:res + printer:sig -> :res } interface IPrinter(T) (T) diff --git a/e2e/struct_builder_verbose/main/main.neva b/e2e/struct_builder_verbose/main/main.neva index 014539e0..6906a198 100644 --- a/e2e/struct_builder_verbose/main/main.neva +++ b/e2e/struct_builder_verbose/main/main.neva @@ -7,16 +7,16 @@ type User struct { } #extern(struct_builder) -def MyStructBuilder(age int, name string) (msg User) +def MyStructBuilder(age int, name string) (res User) def Main(start any) (stop any) { - fmt.Println + println fmt.Println builder MyStructBuilder --- :start -> [ 'John' -> builder:name, 32 -> builder:age ] - builder:msg -> println:data + builder:res -> println:data println:res -> :stop } \ No newline at end of file diff --git a/e2e/struct_builder_with_sugar/main/main.neva b/e2e/struct_builder_with_sugar/main/main.neva index e531ee74..adc6ce06 100644 --- a/e2e/struct_builder_with_sugar/main/main.neva +++ b/e2e/struct_builder_with_sugar/main/main.neva @@ -3,16 +3,14 @@ type User struct { name string } -// FIXME - cannot use 'struct' as a node name - def Main(start any) (stop any) { - fmt.Println - builder Struct + println fmt.Println + builder Struct // FIXME - cannot use 'struct' as a node name --- :start -> [ 'John' -> builder:name, 32 -> builder:age ] - builder:msg -> println:data + builder:res -> println:data println:res -> :stop -} \ No newline at end of file +} diff --git a/e2e/struct_selector_on_port_addr/main/main.neva b/e2e/struct_selector_on_port_addr/main/main.neva index 9b5f9ee1..5ccd7bc1 100644 --- a/e2e/struct_selector_on_port_addr/main/main.neva +++ b/e2e/struct_selector_on_port_addr/main/main.neva @@ -4,12 +4,12 @@ def Main(start any) (stop any) { Foo, fmt.Println --- :start -> foo:sig - foo:msg -> .a -> println:data + foo:res -> .a -> println:data println:res -> :stop } const s struct { a int } = { a: 42 } -def Foo(sig any) (msg struct{a int}) { - :sig -> $s -> :msg +def Foo(sig any) (res struct{a int}) { + :sig -> $s -> :res } diff --git a/examples/fib/main.neva b/examples/fib/main.neva new file mode 100644 index 00000000..b9b35f5f --- /dev/null +++ b/examples/fib/main.neva @@ -0,0 +1,23 @@ +// import { fmt } + +// def Main(start any) (stop any) { +// map_fib Map{Fib} +// --- +// :start -> 0..10 -> ...map_fib -> :res +// } + +// def Fib(data int) (res int) { +// fan_in FanIn +// next Next +// --- +// :data -> switch { +// 0 -> fan_in[0] +// 1 -> fan_in[1] +// _ -> next -> fan_in[2] +// } +// fan_in -> :res +// } + +// def Next(prev int) (res int) { +// ((:prev - 1) + (:prev - 2)) -> :res +// } diff --git a/examples/interfaces/main.neva b/examples/interfaces/main.neva index 84c9e7f9..df922560 100644 --- a/examples/interfaces/main.neva +++ b/examples/interfaces/main.neva @@ -6,10 +6,10 @@ def Main(start any) (stop any) { :start -> wrapper -> :stop } -def Wrapper(msg any) (msg any) { +def Wrapper(data any) (res any) { printer IPrinter --- - :msg -> printer -> :msg + :data -> printer -> :res } interface IPrinter(T) (T) diff --git a/internal/runtime/funcs/del.go b/internal/runtime/funcs/del.go index 725788cd..482111ae 100644 --- a/internal/runtime/funcs/del.go +++ b/internal/runtime/funcs/del.go @@ -9,7 +9,7 @@ import ( type del struct{} func (d del) Create(io runtime.IO, _ runtime.Msg) (func(ctx context.Context), error) { - dataIn, err := io.In.Single("msg") // TODO rename to data? + dataIn, err := io.In.Single("data") if err != nil { return nil, err } diff --git a/internal/runtime/funcs/new.go b/internal/runtime/funcs/new.go index 568c9953..46ca1f7b 100644 --- a/internal/runtime/funcs/new.go +++ b/internal/runtime/funcs/new.go @@ -9,14 +9,14 @@ import ( type new struct{} func (c new) Create(io runtime.IO, cfg runtime.Msg) (func(ctx context.Context), error) { - dataOut, err := io.Out.Single("msg") + resOut, err := io.Out.Single("res") if err != nil { return nil, err } return func(ctx context.Context) { for { - if !dataOut.Send(ctx, cfg) { + if !resOut.Send(ctx, cfg) { return } } diff --git a/internal/runtime/funcs/new_v2.go b/internal/runtime/funcs/new_v2.go index ce157d95..ddb475e4 100644 --- a/internal/runtime/funcs/new_v2.go +++ b/internal/runtime/funcs/new_v2.go @@ -14,7 +14,7 @@ func (c newV2) Create(io runtime.IO, cfg runtime.Msg) (func(ctx context.Context) return nil, err } - resOut, err := io.Out.Single("msg") + resOut, err := io.Out.Single("data") if err != nil { return nil, err } diff --git a/internal/runtime/funcs/panic.go b/internal/runtime/funcs/panic.go index fd79fcf0..e3e473e8 100644 --- a/internal/runtime/funcs/panic.go +++ b/internal/runtime/funcs/panic.go @@ -14,7 +14,7 @@ func (p panicker) Create( io runtime.IO, _ runtime.Msg, ) (func(ctx context.Context), error) { - msgIn, err := io.In.Single("msg") + msgIn, err := io.In.Single("data") if err != nil { return nil, err } diff --git a/internal/runtime/funcs/struct_builder.go b/internal/runtime/funcs/struct_builder.go index 1969d59c..8d9ef637 100644 --- a/internal/runtime/funcs/struct_builder.go +++ b/internal/runtime/funcs/struct_builder.go @@ -26,7 +26,7 @@ func (s structBuilder) Create( inports[inportName] = *inportSlots.Single() } - outport, err := io.Out.Single("msg") + outport, err := io.Out.Single("res") if err != nil { return nil, err } diff --git a/std/builtin/core.neva b/std/builtin/core.neva index 7b47c424..ddb87e15 100644 --- a/std/builtin/core.neva +++ b/std/builtin/core.neva @@ -5,23 +5,23 @@ // Being infinite, it can easily lead to buffer overflow. // New is within small group of components without inports. #extern(new) -pub def New() (msg T) +pub def New() (res T) #extern(new_v2) -pub def NewV2(sig any) (msg T) +pub def NewV2(sig any) (res T) // Del receives and discards the message. // You should avoid using it because compiler will insert it automatically // for every unused outport. // Del is within small group of components without outports. #extern(del) -pub def Del(msg any) () +pub def Del(data any) () // Panic immidiately terminates the program after message is received. // It exits the process with non-zero status code and prints flowtrace to stderr. // Panic is within small group of components without outports. #extern(panic) -pub def Panic(msg any) () +pub def Panic(data any) () // Struct is used to create structures. // Inports for Struct are generated by compiler based on provided type argument @@ -29,7 +29,7 @@ pub def Panic(msg any) () // This is the only component that should use #autoports. #autoports #extern(struct_builder) -pub def Struct () (msg T) +pub def Struct () (res T) // Field is used to access fields of structures. // You prefer dot notation `-> . ->` instead. diff --git a/std/builtin/streams.neva b/std/builtin/streams.neva index 5de1bb97..8c920616 100644 --- a/std/builtin/streams.neva +++ b/std/builtin/streams.neva @@ -55,7 +55,7 @@ pub def Map(data stream) (res stream) { // --- Filter --- pub def Filter(data stream) (res stream) { - split Split{IPredicate} + split Split{predicate IPredicate} s2l StreamToList l2s ListToStream --- From 0f1be1991f14c005a2523046c8b6cc74017dbccc Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Wed, 11 Dec 2024 22:59:18 +0500 Subject: [PATCH 22/28] fix(compiler): add missing changes for port names refactoring --- internal/compiler/analyzer/nodes.go | 7 ++++--- internal/compiler/parser/parser_test.go | 6 +++--- internal/compiler/sourcecode/core/core.go | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/internal/compiler/analyzer/nodes.go b/internal/compiler/analyzer/nodes.go index f6b9cfdb..51345557 100644 --- a/internal/compiler/analyzer/nodes.go +++ b/internal/compiler/analyzer/nodes.go @@ -255,7 +255,7 @@ func (a Analyzer) getNodeInterface( return iface, nil } - // if we here then we have #autoports (only for structs RN) + // if we here then we have #autoports (only for structs) if len(iface.IO.In) != 0 { return src.Interface{}, &compiler.Error{ @@ -322,10 +322,11 @@ func (a Analyzer) getNodeInterface( IO: src.IO{ In: inports, Out: map[string]src.Port{ - "msg": { + // struct builder has exactly one outport - created structure + "res": { TypeExpr: resolvedNodeArg, IsArray: false, - Meta: iface.IO.Out["msg"].Meta, + Meta: iface.IO.Out["res"].Meta, }, }, }, diff --git a/internal/compiler/parser/parser_test.go b/internal/compiler/parser/parser_test.go index 8dd34afa..6303b7ce 100644 --- a/internal/compiler/parser/parser_test.go +++ b/internal/compiler/parser/parser_test.go @@ -234,9 +234,9 @@ func TestParser_ParseFile_ChainedConnectionsWithConstants(t *testing.T) { { name: "const ref in chain", text: ` - const msg string = 'hello' + const greeting string = 'hello' def C1() () { - :start -> $msg -> :stop + :start -> $greeting -> :stop } `, check: func(t *testing.T, net []src.Connection) { @@ -246,7 +246,7 @@ func TestParser_ParseFile_ChainedConnectionsWithConstants(t *testing.T) { chain := conn.Receivers[0].ChainedConnection.Normal require.NotNil(t, chain.Senders[0].Const) - require.Equal(t, "msg", chain.Senders[0].Const.Value.Ref.Name) + require.Equal(t, "greeting", chain.Senders[0].Const.Value.Ref.Name) require.Equal(t, "out", chain.Receivers[0].PortAddr.Node) require.Equal(t, "stop", chain.Receivers[0].PortAddr.Port) }, diff --git a/internal/compiler/sourcecode/core/core.go b/internal/compiler/sourcecode/core/core.go index a18bb3eb..649627f2 100644 --- a/internal/compiler/sourcecode/core/core.go +++ b/internal/compiler/sourcecode/core/core.go @@ -27,7 +27,7 @@ type Meta struct { Text string `json:"text,omitempty"` Start Position `json:"start,omitempty"` Stop Position `json:"stop,omitempty"` - Location Location `json:"location,omitempty"` + Location Location `json:"location,omitempty"` // Location must always be present, even for virtual nodes inserted after resugaring, because irgen relies on it. } type Location struct { From fc70d7cf01240f39da4b4f72d7b028f05bdc3108 Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Sat, 14 Dec 2024 00:14:55 +0500 Subject: [PATCH 23/28] wip(compiler): adding meta everywhere; feat(desugarer): reset counters after each component; refactor(stdlib): some fixes after renaming ports --- examples/fizzbuzz/main.neva | 7 +- internal/compiler/analyzer/component.go | 9 +- internal/compiler/analyzer/network.go | 1 + internal/compiler/desugarer/component.go | 10 +- internal/compiler/desugarer/const.go | 1 + internal/compiler/desugarer/del.go | 20 +- internal/compiler/desugarer/desugarer.go | 67 ++++- internal/compiler/desugarer/network.go | 251 +++++++++++++++--- internal/compiler/desugarer/network_test.go | 14 +- internal/compiler/desugarer/node.go | 97 ++++--- .../compiler/desugarer/struct_selectors.go | 27 +- internal/compiler/irgen/irgen.go | 23 +- internal/compiler/irgen/network.go | 14 +- internal/compiler/parser/listener_helpers.go | 33 +-- internal/runtime/funcs/int_mod.go | 15 +- internal/runtime/funcs/new_v2.go | 4 +- internal/runtime/message.go | 26 +- 17 files changed, 462 insertions(+), 157 deletions(-) diff --git a/examples/fizzbuzz/main.neva b/examples/fizzbuzz/main.neva index 51bddee8..b1f3eb57 100644 --- a/examples/fizzbuzz/main.neva +++ b/examples/fizzbuzz/main.neva @@ -8,8 +8,11 @@ def Main(start any) (stop any) { :start -> 1..101 -> map -> for -> wait -> :stop } -def FizzBuzz(data int) (res string|int) { - Select, Mod15, Mod3, Mod5 +def FizzBuzz(data int) (res string | int) { + select Select + mod15 Mod15 + mod3 Mod3 + mod5 Mod5 --- :data -> [mod15, select:then[3]] diff --git a/internal/compiler/analyzer/component.go b/internal/compiler/analyzer/component.go index d6b5d509..b86445e9 100644 --- a/internal/compiler/analyzer/component.go +++ b/internal/compiler/analyzer/component.go @@ -49,8 +49,8 @@ func (a Analyzer) analyzeComponent( if isRuntimeFunc { if len(component.Nodes) != 0 || len(component.Net) != 0 { return src.Component{}, &compiler.Error{ - Message: "Component with nodes or network cannot use #extern directive", - Meta: &component.Meta, + Message: "Component with nodes or network cannot use #extern directive", + Meta: &component.Meta, } } return component, nil @@ -69,8 +69,8 @@ func (a Analyzer) analyzeComponent( if len(component.Net) == 0 { return src.Component{}, &compiler.Error{ - Message: "Component must have network", - Meta: &component.Meta, + Message: "Component must have network", + Meta: &component.Meta, } } @@ -92,5 +92,6 @@ func (a Analyzer) analyzeComponent( Interface: resolvedInterface, Nodes: resolvedNodes, Net: analyzedNet, + Meta: component.Meta, }, nil } diff --git a/internal/compiler/analyzer/network.go b/internal/compiler/analyzer/network.go index 37fafbb2..3e49a9b6 100644 --- a/internal/compiler/analyzer/network.go +++ b/internal/compiler/analyzer/network.go @@ -163,6 +163,7 @@ func (a Analyzer) analyzeNormalConnection( return &src.NormalConnection{ Senders: analyzedSenders, Receivers: analyzedReceiverSide, + Meta: normConn.Meta, }, nil } diff --git a/internal/compiler/desugarer/component.go b/internal/compiler/desugarer/component.go index 737a01d0..5a672321 100644 --- a/internal/compiler/desugarer/component.go +++ b/internal/compiler/desugarer/component.go @@ -22,7 +22,7 @@ func (d *Desugarer) desugarComponent( virtualEntities := map[string]src.Entity{} - desugaredNodes, virtConnsForNodes, err := d.desugarNodes( + desugaredNodes, virtualConnections, err := d.desugarNodes( component, scope, virtualEntities, @@ -31,11 +31,11 @@ func (d *Desugarer) desugarComponent( return handleComponentResult{}, err } - netToDesugar := append(virtConnsForNodes, component.Net...) + connectionsToDesugar := append(virtualConnections, component.Net...) desugarNetResult, err := d.desugarNetwork( component.Interface, - netToDesugar, + connectionsToDesugar, desugaredNodes, scope, ) @@ -63,9 +63,9 @@ func (d *Desugarer) desugarComponent( desugarNetResult.nodesPortsUsed, ) if unusedOutports.len() != 0 { - unusedOutportsResult := d.handleUnusedOutports(unusedOutports) + unusedOutportsResult := d.handleUnusedOutports(unusedOutports, component.Meta) desugaredNetwork = append(desugaredNetwork, unusedOutportsResult.virtualConnections...) - desugaredNodes[unusedOutportsResult.voidNodeName] = unusedOutportsResult.voidNode + desugaredNodes[unusedOutportsResult.voidNodeName] = unusedOutportsResult.delNode } return handleComponentResult{ diff --git a/internal/compiler/desugarer/const.go b/internal/compiler/desugarer/const.go index a76dbbb4..8b51fc12 100644 --- a/internal/compiler/desugarer/const.go +++ b/internal/compiler/desugarer/const.go @@ -21,6 +21,7 @@ func (d *Desugarer) handleConst(constant src.Const) (src.Const, error) { Value: src.ConstValue{ Message: &src.MsgLiteral{ Float: compiler.Pointer(float64(*constant.Value.Message.Int)), + Meta: constant.Meta, }, }, }, nil diff --git a/internal/compiler/desugarer/del.go b/internal/compiler/desugarer/del.go index d8ece76d..9d45acde 100644 --- a/internal/compiler/desugarer/del.go +++ b/internal/compiler/desugarer/del.go @@ -7,20 +7,25 @@ import ( type unusedOutportsResult struct { voidNodeName string - voidNode src.Node + delNode src.Node virtualConnections []src.Connection } -func (Desugarer) handleUnusedOutports(unusedOutports nodeOutportsUsed) unusedOutportsResult { +func (Desugarer) handleUnusedOutports( + unusedOutports nodeOutportsUsed, + meta core.Meta, +) unusedOutportsResult { destructorNodeName := "__del__" result := unusedOutportsResult{ voidNodeName: destructorNodeName, - voidNode: src.Node{ + delNode: src.Node{ EntityRef: core.EntityRef{ Pkg: "builtin", Name: "Del", + Meta: meta, }, + Meta: meta, }, virtualConnections: make([]src.Connection, 0, len(unusedOutports.m)), } @@ -29,8 +34,10 @@ func (Desugarer) handleUnusedOutports(unusedOutports nodeOutportsUsed) unusedOut { PortAddr: &src.PortAddr{ Node: destructorNodeName, - Port: "msg", + Port: "data", + Meta: meta, }, + Meta: meta, }, } @@ -44,12 +51,15 @@ func (Desugarer) handleUnusedOutports(unusedOutports nodeOutportsUsed) unusedOut PortAddr: &src.PortAddr{ Node: nodeName, Port: portName, + Meta: meta, }, + Meta: meta, }, }, Receivers: receiverSides, + Meta: meta, }, - Meta: core.Meta{}, + Meta: meta, }) } } diff --git a/internal/compiler/desugarer/desugarer.go b/internal/compiler/desugarer/desugarer.go index bf1df3ad..e114e270 100644 --- a/internal/compiler/desugarer/desugarer.go +++ b/internal/compiler/desugarer/desugarer.go @@ -158,9 +158,12 @@ func (d *Desugarer) desugarFile( return src.File{}, fmt.Errorf("desugar entity %s: %w", entityName, err) } + d.resetCounters() + desugaredEntities[entityName] = entityResult.entity - for name, entityToInsert := range entityResult.entitiesToInsert { + // insert virtual entities, created by desugaring of the entity + for name, entityToInsert := range entityResult.insert { desugaredEntities[name] = entityToInsert } } @@ -173,6 +176,7 @@ func (d *Desugarer) desugarFile( desugaredImports["builtin"] = src.Import{ // inject std/builtin import Module: "std", Package: "builtin", + Meta: core.Meta{Location: *scope.Location()}, } return src.File{ @@ -182,8 +186,8 @@ func (d *Desugarer) desugarFile( } type desugarEntityResult struct { - entity src.Entity - entitiesToInsert map[string]src.Entity + entity src.Entity + insert map[string]src.Entity } func (d *Desugarer) desugarEntity( @@ -215,7 +219,7 @@ func (d *Desugarer) desugarEntity( } return desugarEntityResult{ - entitiesToInsert: componentResult.virtualEntities, + insert: componentResult.virtualEntities, entity: src.Entity{ IsPublic: entity.IsPublic, Kind: entity.Kind, @@ -224,6 +228,61 @@ func (d *Desugarer) desugarEntity( }, nil } +func (d *Desugarer) resetCounters() { + d.virtualSelectorsCount = 0 + d.ternaryCounter = 0 + d.switchCounter = 0 + d.virtualLocksCounter = 0 + d.virtualEmittersCount = 0 + d.virtualConstCount = 0 + d.virtualTriggersCount = 0 + d.fanOutCounter = 0 + d.fanInCounter = 0 + d.rangeCounter = 0 + // + d.addCounter = 0 + d.subCounter = 0 + d.mulCounter = 0 + d.divCounter = 0 + d.modCounter = 0 + d.powCounter = 0 + // + d.eqCounter = 0 + d.neCounter = 0 + d.gtCounter = 0 + d.ltCounter = 0 + d.geCounter = 0 + d.leCounter = 0 + // + d.andCounter = 0 + d.orCounter = 0 + d.bitAndCounter = 0 + d.bitOrCounter = 0 + d.bitXorCounter = 0 + d.bitLshCounter = 0 + d.bitRshCounter = 0 + d.mulCounter = 0 + d.divCounter = 0 + d.modCounter = 0 + d.powCounter = 0 + // + d.eqCounter = 0 + d.neCounter = 0 + d.gtCounter = 0 + d.ltCounter = 0 + d.geCounter = 0 + d.leCounter = 0 + // + d.andCounter = 0 + d.orCounter = 0 + // + d.bitAndCounter = 0 + d.bitOrCounter = 0 + d.bitXorCounter = 0 + d.bitLshCounter = 0 + d.bitRshCounter = 0 +} + func New() Desugarer { return Desugarer{} } diff --git a/internal/compiler/desugarer/network.go b/internal/compiler/desugarer/network.go index 801589e8..fca0cf97 100644 --- a/internal/compiler/desugarer/network.go +++ b/internal/compiler/desugarer/network.go @@ -97,7 +97,7 @@ func (d *Desugarer) desugarConnection( nodesToInsert map[string]src.Node, constsToInsert map[string]src.Const, ) (desugarConnectionResult, error) { - if conn.ArrayBypass != nil { + if conn.ArrayBypass != nil { // nothing to desugar, just mark ports as used nodePortsUsed.set( conn.ArrayBypass.SenderOutport.Node, conn.ArrayBypass.SenderOutport.Port, @@ -129,7 +129,7 @@ func (d *Desugarer) desugarNormalConnection( nodesToInsert map[string]src.Node, constsToInsert map[string]src.Const, ) (desugarConnectionResult, error) { - if len(normConn.Senders) > 1 { + if fanIn := len(normConn.Senders) > 1; fanIn { result, err := d.desugarFanIn( iface, normConn, @@ -142,7 +142,8 @@ func (d *Desugarer) desugarNormalConnection( if err != nil { return desugarConnectionResult{}, fmt.Errorf("desugar fan in: %w", err) } - return desugarConnectionResult{insert: result}, nil // original connection is replaced by multiple new ones + // one fan-in connection was replaced by multiple desugared ones + return desugarConnectionResult{insert: result}, nil } desugarSenderResult, err := d.desugarSingleSender( @@ -161,6 +162,7 @@ func (d *Desugarer) desugarNormalConnection( normConn = *desugarSenderResult.replace.Normal insert := desugarSenderResult.insert + // We need to first degugar fan-out and convert it to a single receiver in this connection if len(normConn.Receivers) > 1 { result, err := d.desugarFanOut( iface, @@ -205,6 +207,7 @@ type desugarReceiverResult struct { insert []src.Connection } +// desugarSingleReceiver expects connection without fan-out (it must be desugared before). func (d *Desugarer) desugarSingleReceiver( iface src.Interface, normConn src.NormalConnection, @@ -214,6 +217,8 @@ func (d *Desugarer) desugarSingleReceiver( constsToInsert map[string]src.Const, nodePortsUsed nodeOutportsUsed, ) (desugarReceiverResult, error) { + locOnlyMeta := core.Meta{Location: normConn.Senders[0].Meta.Location} // FIXME for some reason normConn.Meta sometimes empty + receiver := normConn.Receivers[0] if receiver.PortAddr != nil { @@ -224,6 +229,7 @@ func (d *Desugarer) desugarSingleReceiver( Senders: normConn.Senders, Receivers: []src.ConnectionReceiver{receiver}, }, + Meta: locOnlyMeta, }, insert: []src.Connection{}, }, nil @@ -250,7 +256,9 @@ func (d *Desugarer) desugarSingleReceiver( }, }, }, + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, }, }, nil } @@ -280,7 +288,9 @@ func (d *Desugarer) desugarSingleReceiver( EntityRef: core.EntityRef{ Pkg: "builtin", Name: "Switch", + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, } // Connect original sender to switch:data @@ -292,10 +302,13 @@ func (d *Desugarer) desugarSingleReceiver( PortAddr: &src.PortAddr{ Node: switchNodeName, Port: "data", + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, }, }, }, + Meta: locOnlyMeta, } insert := []src.Connection{} @@ -312,10 +325,13 @@ func (d *Desugarer) desugarSingleReceiver( Node: switchNodeName, Port: "case", Idx: compiler.Pointer(uint8(i)), + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, }, }, }, + Meta: locOnlyMeta, }) // Connect switch:case[i] to case receiver @@ -327,11 +343,14 @@ func (d *Desugarer) desugarSingleReceiver( Node: switchNodeName, Port: "case", Idx: compiler.Pointer(uint8(i)), + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, }, }, Receivers: caseConn.Receivers, }, + Meta: locOnlyMeta, }) } @@ -343,10 +362,13 @@ func (d *Desugarer) desugarSingleReceiver( PortAddr: &src.PortAddr{ Node: switchNodeName, Port: "else", + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, }, }, Receivers: receiver.Switch.Default, + Meta: locOnlyMeta, }, }) @@ -424,6 +446,8 @@ func (d *Desugarer) desugarChainedConnection( panic("unexpected chain head type") } + locOnlyMeta := core.Meta{Location: chainHead.Meta.Location} + if chainHead.Const != nil { d.virtualTriggersCount++ triggerNodeName := fmt.Sprintf("__newv2__%d", d.virtualTriggersCount) @@ -435,11 +459,16 @@ func (d *Desugarer) desugarChainedConnection( } nodesToInsert[triggerNodeName] = src.Node{ - EntityRef: core.EntityRef{Pkg: "builtin", Name: "NewV2"}, - TypeArgs: []ts.Expr{constTypeExpr}, + EntityRef: core.EntityRef{ + Pkg: "builtin", + Name: "NewV2", + Meta: locOnlyMeta, + }, + TypeArgs: []ts.Expr{constTypeExpr}, Directives: map[src.Directive][]string{ compiler.BindDirective: {chainHead.Const.Value.Ref.String()}, }, + Meta: locOnlyMeta, } } else { d.virtualConstCount++ @@ -447,19 +476,28 @@ func (d *Desugarer) desugarChainedConnection( constsToInsert[virtualConstName] = *chainHead.Const nodesToInsert[triggerNodeName] = src.Node{ - EntityRef: core.EntityRef{Pkg: "builtin", Name: "NewV2"}, - TypeArgs: []ts.Expr{chainHead.Const.TypeExpr}, + EntityRef: core.EntityRef{ + Pkg: "builtin", + Name: "NewV2", + Meta: locOnlyMeta, + }, + TypeArgs: []ts.Expr{chainHead.Const.TypeExpr}, Directives: map[src.Directive][]string{ compiler.BindDirective: {virtualConstName}, }, + Meta: locOnlyMeta, } } chainedConn.Normal.Senders = []src.ConnectionSender{ - {PortAddr: &src.PortAddr{ - Node: triggerNodeName, - Port: "msg", - }}, + { + PortAddr: &src.PortAddr{ + Node: triggerNodeName, + Port: "res", + Meta: locOnlyMeta, + }, + Meta: locOnlyMeta, + }, } } @@ -489,8 +527,10 @@ func (d *Desugarer) desugarChainedConnection( Idx: desugaredHead.PortAddr.Idx, Meta: chainHead.Meta, }, + Meta: chainHead.Meta, }, }, + Meta: locOnlyMeta, }, } @@ -540,6 +580,8 @@ func (d *Desugarer) desugarDeferredConnection( return desugarDeferredConnectionsResult{}, err } + locOnlyMeta := core.Meta{Location: deferredConnection.Meta.Location} + deferredConnection = *desugarDeferredConnResult.replace connsToInsert := desugarDeferredConnResult.insert @@ -550,14 +592,17 @@ func (d *Desugarer) desugarDeferredConnection( EntityRef: core.EntityRef{ Pkg: "builtin", Name: "Lock", + Meta: locOnlyMeta, }, TypeArgs: []typesystem.Expr{ ts.Expr{ Inst: &typesystem.InstExpr{ Ref: core.EntityRef{Pkg: "builtin", Name: "any"}, }, + Meta: locOnlyMeta, }, }, + Meta: locOnlyMeta, } // 2) connect original sender to lock receiver @@ -569,6 +614,7 @@ func (d *Desugarer) desugarDeferredConnection( PortAddr: &src.PortAddr{ Node: lockNodeName, Port: "sig", + Meta: locOnlyMeta, }, }, }, @@ -586,9 +632,11 @@ func (d *Desugarer) desugarDeferredConnection( PortAddr: &src.PortAddr{ Node: lockNodeName, Port: "data", + Meta: locOnlyMeta, }, }, }, + Meta: locOnlyMeta, }, }, // 4) create connection from lock:data to receiver-side of deferred connection @@ -599,10 +647,12 @@ func (d *Desugarer) desugarDeferredConnection( PortAddr: &src.PortAddr{ Node: lockNodeName, Port: "data", + Meta: locOnlyMeta, }, }, }, Receivers: deferredConnection.Normal.Receivers, + Meta: locOnlyMeta, }, }, ) @@ -641,11 +691,12 @@ func (d *Desugarer) desugarSingleSender( normConn.Senders = []src.ConnectionSender{ { PortAddr: &src.PortAddr{ - Port: portName, + Port: portName, // <- desugaring Node: sender.PortAddr.Node, Idx: sender.PortAddr.Idx, Meta: sender.PortAddr.Meta, }, + Meta: sender.Meta, }, } } @@ -686,8 +737,11 @@ func (d *Desugarer) desugarSingleSender( } return desugarSenderResult{ - replace: src.Connection{Normal: replacedConnDesugarRes.replace.Normal}, - insert: replacedConnDesugarRes.insert, + replace: src.Connection{ + Normal: replacedConnDesugarRes.replace.Normal, + Meta: replacedConnDesugarRes.replace.Meta, + }, + insert: replacedConnDesugarRes.insert, }, nil } @@ -794,12 +848,19 @@ func (d *Desugarer) handleLiteralSender( d.virtualEmittersCount++ emitterNodeName := fmt.Sprintf("__new__%d", d.virtualEmittersCount) + locOnlyMeta := core.Meta{Location: constant.Meta.Location} + emitterNode := src.Node{ Directives: map[src.Directive][]string{ compiler.BindDirective: {constName}, }, - EntityRef: newComponentRef, - TypeArgs: []ts.Expr{constant.TypeExpr}, + EntityRef: core.EntityRef{ + Pkg: newComponentRef.Pkg, + Name: newComponentRef.Name, + Meta: locOnlyMeta, + }, + TypeArgs: []ts.Expr{constant.TypeExpr}, + Meta: locOnlyMeta, } nodesToInsert[emitterNodeName] = emitterNode @@ -807,7 +868,7 @@ func (d *Desugarer) handleLiteralSender( emitterNodeOutportAddr := src.PortAddr{ Node: emitterNodeName, - Port: "msg", + Port: "res", } return emitterNodeOutportAddr, nil @@ -823,6 +884,8 @@ func (d *Desugarer) handleConstRefSender( return src.PortAddr{}, fmt.Errorf("get const type by ref: %w", err) } + locOnlyMeta := core.Meta{Location: ref.Meta.Location} + d.virtualEmittersCount++ virtualEmitterName := fmt.Sprintf("__new__%d", d.virtualEmittersCount) @@ -831,13 +894,19 @@ func (d *Desugarer) handleConstRefSender( Directives: map[src.Directive][]string{ compiler.BindDirective: {ref.String()}, }, - EntityRef: newComponentRef, - TypeArgs: []ts.Expr{constTypeExpr}, + EntityRef: core.EntityRef{ + Pkg: newComponentRef.Pkg, + Name: newComponentRef.Name, + Meta: locOnlyMeta, + }, + TypeArgs: []ts.Expr{constTypeExpr}, + Meta: locOnlyMeta, } emitterNodeOutportAddr := src.PortAddr{ Node: virtualEmitterName, - Port: "msg", + Port: "res", + Meta: locOnlyMeta, } nodesToInsert[virtualEmitterName] = emitterNode @@ -882,20 +951,26 @@ func (d *Desugarer) desugarFanOut( nodes map[string]src.Node, ) (desugarFanOutResult, error) { d.fanOutCounter++ - nodeName := fmt.Sprintf("__fanOut__%d", d.fanOutCounter) + nodeName := fmt.Sprintf("__fan_out__%d", d.fanOutCounter) + + locOnlyMeta := core.Meta{Location: normConn.Senders[0].Meta.Location} // FIXME for some reason norm-conn sometimes doesn't have meta nodesToInsert[nodeName] = src.Node{ EntityRef: core.EntityRef{ Name: "FanOut", Pkg: "builtin", + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, } receiverToReplace := src.ConnectionReceiver{ PortAddr: &src.PortAddr{ Node: nodeName, Port: "data", + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, } insert := make([]src.Connection, 0, len(normConn.Receivers)) @@ -908,10 +983,13 @@ func (d *Desugarer) desugarFanOut( Node: nodeName, Port: "data", Idx: compiler.Pointer(uint8(i)), + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, }, }, Receivers: []src.ConnectionReceiver{receiver}, + Meta: locOnlyMeta, }, } @@ -937,7 +1015,9 @@ func (d *Desugarer) desugarFanOut( Normal: &src.NormalConnection{ Senders: normConn.Senders, // senders must be desugared Receivers: []src.ConnectionReceiver{receiverToReplace}, + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, }, insert: insert, }, nil @@ -958,6 +1038,8 @@ func (d *Desugarer) desugarRangeSender( nodesToInsert map[string]src.Node, constsToInsert map[string]src.Const, ) (handleRangeSenderResult, error) { + locOnlyMeta := core.Meta{Location: rangeExpr.Meta.Location} + d.rangeCounter++ rangeNodeName := fmt.Sprintf("__range%d__", d.rangeCounter) @@ -967,32 +1049,53 @@ func (d *Desugarer) desugarRangeSender( constsToInsert[fromConstName] = src.Const{ TypeExpr: ts.Expr{Inst: &ts.InstExpr{Ref: core.EntityRef{Pkg: "builtin", Name: "int"}}}, Value: src.ConstValue{Message: &src.MsgLiteral{Int: compiler.Pointer(int(rangeExpr.From))}}, + Meta: locOnlyMeta, } constsToInsert[toConstName] = src.Const{ TypeExpr: ts.Expr{Inst: &ts.InstExpr{Ref: core.EntityRef{Pkg: "builtin", Name: "int"}}}, Value: src.ConstValue{Message: &src.MsgLiteral{Int: compiler.Pointer(int(rangeExpr.To))}}, + Meta: locOnlyMeta, } nodesToInsert[rangeNodeName] = src.Node{ - EntityRef: core.EntityRef{Pkg: "builtin", Name: "Range"}, + EntityRef: core.EntityRef{ + Pkg: "builtin", + Name: "Range", + Meta: locOnlyMeta, + }, + Meta: locOnlyMeta, } nodesToInsert[fromConstName] = src.Node{ - EntityRef: core.EntityRef{Pkg: "builtin", Name: "New"}, + EntityRef: core.EntityRef{ + Pkg: "builtin", + Name: "New", + Meta: locOnlyMeta, + }, Directives: map[src.Directive][]string{ "bind": {fromConstName}, }, + Meta: locOnlyMeta, } nodesToInsert[toConstName] = src.Node{ - EntityRef: core.EntityRef{Pkg: "builtin", Name: "New"}, + EntityRef: core.EntityRef{ + Pkg: "builtin", + Name: "New", + Meta: locOnlyMeta, + }, Directives: map[src.Directive][]string{ "bind": {toConstName}, }, + Meta: locOnlyMeta, } replace := src.NormalConnection{ Senders: []src.ConnectionSender{ { - PortAddr: &src.PortAddr{Node: rangeNodeName, Port: "res"}, + PortAddr: &src.PortAddr{ + Node: rangeNodeName, + Port: "res", + Meta: locOnlyMeta, + }, }, }, Receivers: normConn.Receivers, @@ -1004,30 +1107,50 @@ func (d *Desugarer) desugarRangeSender( Normal: &src.NormalConnection{ Senders: []src.ConnectionSender{ { - PortAddr: &src.PortAddr{Node: fromConstName, Port: "msg"}, + PortAddr: &src.PortAddr{ + Node: fromConstName, + Port: "res", + Meta: locOnlyMeta, + }, }, }, Receivers: []src.ConnectionReceiver{ { - PortAddr: &src.PortAddr{Node: rangeNodeName, Port: "from"}, + PortAddr: &src.PortAddr{ + Node: rangeNodeName, + Port: "from", + Meta: locOnlyMeta, + }, }, }, + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, }, // $to -> range:to { Normal: &src.NormalConnection{ Senders: []src.ConnectionSender{ { - PortAddr: &src.PortAddr{Node: toConstName, Port: "msg"}, + PortAddr: &src.PortAddr{ + Node: toConstName, + Port: "res", + Meta: locOnlyMeta, + }, }, }, Receivers: []src.ConnectionReceiver{ { - PortAddr: &src.PortAddr{Node: rangeNodeName, Port: "to"}, + PortAddr: &src.PortAddr{ + Node: rangeNodeName, + Port: "to", + Meta: locOnlyMeta, + }, }, }, + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, }, } @@ -1048,7 +1171,11 @@ func (d *Desugarer) desugarFanIn( scope Scope, nodes map[string]src.Node, ) ([]src.Connection, error) { - // 1. insert unique fan-in node + locOnlyMeta := core.Meta{ + Location: *scope.Location(), + } + + // 1. create fan-in node with unique name and insert into nodes d.fanInCounter++ fanInNodeName := fmt.Sprintf("__fanIn__%d", d.fanInCounter) nodesToInsert[fanInNodeName] = src.Node{ @@ -1056,46 +1183,52 @@ func (d *Desugarer) desugarFanIn( Pkg: "builtin", Name: "FanIn", }, + Meta: locOnlyMeta, } - // 2. connection each sender with fan-in node - netWithoutFanIn := make([]src.Connection, 0, len(normConn.Senders)) - for i, sender := range normConn.Senders { - netWithoutFanIn = append(netWithoutFanIn, src.Connection{ + // 2. connect each sender of this connection with fan-in node + desugaredFanIn := make([]src.Connection, 0, len(normConn.Senders)) + for i, originalSender := range normConn.Senders { + desugaredFanIn = append(desugaredFanIn, src.Connection{ Normal: &src.NormalConnection{ - Senders: []src.ConnectionSender{sender}, + Senders: []src.ConnectionSender{originalSender}, Receivers: []src.ConnectionReceiver{ { PortAddr: &src.PortAddr{ Node: fanInNodeName, Port: "data", Idx: compiler.Pointer(uint8(i)), + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, }, }, }, }) } - // 3. insert new connection from fan-in to original receivers - netWithoutFanIn = append(netWithoutFanIn, src.Connection{ + // 3. insert new connection: fan_in -> original receivers + desugaredFanIn = append(desugaredFanIn, src.Connection{ Normal: &src.NormalConnection{ Senders: []src.ConnectionSender{ { PortAddr: &src.PortAddr{ Node: fanInNodeName, Port: "res", + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, }, }, Receivers: normConn.Receivers, + Meta: locOnlyMeta, }, }) // 4. desugar each connection (original senders and receivers might need it) desugaredConnections, err := d.desugarConnections( iface, - netWithoutFanIn, + desugaredFanIn, nodePortsUsed, scope, nodes, @@ -1130,6 +1263,8 @@ func (d *Desugarer) desugarTernarySender( scope Scope, nodes map[string]src.Node, ) (handleTernarySenderResult, error) { + locOnlyMeta := core.Meta{Location: ternary.Meta.Location} + d.ternaryCounter++ ternaryNodeName := fmt.Sprintf("__ternary__%d", d.ternaryCounter) @@ -1137,7 +1272,9 @@ func (d *Desugarer) desugarTernarySender( EntityRef: core.EntityRef{ Pkg: "builtin", Name: "Ternary", + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, } sugaredInsert := []src.Connection{ @@ -1150,10 +1287,13 @@ func (d *Desugarer) desugarTernarySender( PortAddr: &src.PortAddr{ Node: ternaryNodeName, Port: "if", + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, }, }, }, + Meta: locOnlyMeta, }, // 2) left -> ternary:then { @@ -1164,9 +1304,12 @@ func (d *Desugarer) desugarTernarySender( PortAddr: &src.PortAddr{ Node: ternaryNodeName, Port: "then", + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, }, }, + Meta: locOnlyMeta, }, }, // right -> ternary:else @@ -1175,10 +1318,17 @@ func (d *Desugarer) desugarTernarySender( Senders: []src.ConnectionSender{ternary.Right}, Receivers: []src.ConnectionReceiver{ { - PortAddr: &src.PortAddr{Node: ternaryNodeName, Port: "else"}, + PortAddr: &src.PortAddr{ + Node: ternaryNodeName, + Port: "else", + Meta: locOnlyMeta, + }, + Meta: locOnlyMeta, }, }, + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, }, } @@ -1208,10 +1358,12 @@ func (d *Desugarer) desugarTernarySender( PortAddr: &src.PortAddr{ Node: ternaryNodeName, Port: "res", + Meta: locOnlyMeta, }, }, }, Receivers: normConn.Receivers, + Meta: locOnlyMeta, }, } @@ -1236,6 +1388,8 @@ func (d *Desugarer) desugarBinarySender( scope Scope, nodes map[string]src.Node, ) (handleBinarySenderResult, error) { + locOnlyMeta := core.Meta{Location: binary.Meta.Location} + var ( opNode string opComponent string @@ -1330,8 +1484,10 @@ func (d *Desugarer) desugarBinarySender( EntityRef: core.EntityRef{ Pkg: "builtin", Name: opComponent, + Meta: locOnlyMeta, }, TypeArgs: []ts.Expr{binary.AnalyzedType}, + Meta: locOnlyMeta, } // left -> op:left @@ -1342,9 +1498,14 @@ func (d *Desugarer) desugarBinarySender( Senders: []src.ConnectionSender{binary.Left}, Receivers: []src.ConnectionReceiver{ { - PortAddr: &src.PortAddr{Node: opNode, Port: "left"}, + PortAddr: &src.PortAddr{ + Node: opNode, + Port: "left", + Meta: locOnlyMeta, + }, }, }, + Meta: locOnlyMeta, }, }, { @@ -1352,10 +1513,15 @@ func (d *Desugarer) desugarBinarySender( Senders: []src.ConnectionSender{binary.Right}, Receivers: []src.ConnectionReceiver{ { - PortAddr: &src.PortAddr{Node: opNode, Port: "right"}, + PortAddr: &src.PortAddr{ + Node: opNode, + Port: "right", + Meta: locOnlyMeta, + }, }, }, }, + Meta: locOnlyMeta, }, } @@ -1386,11 +1552,14 @@ func (d *Desugarer) desugarBinarySender( PortAddr: &src.PortAddr{ Node: opNode, Port: "res", + Meta: locOnlyMeta, }, }, }, Receivers: normConn.Receivers, // desugaring of original receivers is job of caller + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, } return handleBinarySenderResult{ diff --git a/internal/compiler/desugarer/network_test.go b/internal/compiler/desugarer/network_test.go index 16b872f8..707924cc 100644 --- a/internal/compiler/desugarer/network_test.go +++ b/internal/compiler/desugarer/network_test.go @@ -568,7 +568,7 @@ func TestDesugarNetwork(t *testing.T) { Normal: &src.NormalConnection{ Senders: []src.ConnectionSender{ { - PortAddr: &src.PortAddr{Node: "__new__1", Port: "msg"}, + PortAddr: &src.PortAddr{Node: "__new__1", Port: "res"}, }, }, Receivers: []src.ConnectionReceiver{ @@ -670,7 +670,7 @@ func TestDesugarNetwork(t *testing.T) { Normal: &src.NormalConnection{ Senders: []src.ConnectionSender{ { - PortAddr: &src.PortAddr{Node: "__newv2__1", Port: "msg"}, + PortAddr: &src.PortAddr{Node: "__newv2__1", Port: "res"}, }, }, Receivers: []src.ConnectionReceiver{ @@ -764,7 +764,7 @@ func TestDesugarNetwork(t *testing.T) { Normal: &src.NormalConnection{ Senders: []src.ConnectionSender{ { - PortAddr: &src.PortAddr{Node: "__newv2__1", Port: "msg"}, + PortAddr: &src.PortAddr{Node: "__newv2__1", Port: "res"}, }, }, Receivers: []src.ConnectionReceiver{ @@ -869,10 +869,10 @@ func TestDesugarNetwork(t *testing.T) { }, }, { - // __new__1:msg -> __add__1:left + // __new__1:res -> __add__1:left Normal: &src.NormalConnection{ Senders: []src.ConnectionSender{ - {PortAddr: &src.PortAddr{Node: "__new__1", Port: "msg"}}, + {PortAddr: &src.PortAddr{Node: "__new__1", Port: "res"}}, }, Receivers: []src.ConnectionReceiver{ {PortAddr: &src.PortAddr{Node: "__add__1", Port: "left"}}, @@ -880,10 +880,10 @@ func TestDesugarNetwork(t *testing.T) { }, }, { - // __new__2:msg -> __add__1:right + // __new__2:res -> __add__1:right Normal: &src.NormalConnection{ Senders: []src.ConnectionSender{ - {PortAddr: &src.PortAddr{Node: "__new__2", Port: "msg"}}, + {PortAddr: &src.PortAddr{Node: "__new__2", Port: "res"}}, }, Receivers: []src.ConnectionReceiver{ {PortAddr: &src.PortAddr{Node: "__add__1", Port: "right"}}, diff --git a/internal/compiler/desugarer/node.go b/internal/compiler/desugarer/node.go index 8d082a18..c725d9de 100644 --- a/internal/compiler/desugarer/node.go +++ b/internal/compiler/desugarer/node.go @@ -18,6 +18,8 @@ func (Desugarer) handleNode( ) ([]src.Connection, error) { var extraConnections []src.Connection + locOnlyMeta := core.Meta{Location: node.Meta.Location} + if node.ErrGuard { extraConnections = append(extraConnections, src.Connection{ Normal: &src.NormalConnection{ @@ -26,7 +28,9 @@ func (Desugarer) handleNode( PortAddr: &src.PortAddr{ Node: nodeName, Port: "err", + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, }, }, Receivers: []src.ConnectionReceiver{ @@ -34,92 +38,119 @@ func (Desugarer) handleNode( PortAddr: &src.PortAddr{ Node: "out", Port: "err", + Meta: locOnlyMeta, }, }, }, }, + Meta: locOnlyMeta, }) } - entity, _, err := scope.Entity(node.EntityRef) + nodeEntity, _, err := scope.Entity(node.EntityRef) if err != nil { return nil, fmt.Errorf("get entity: %w", err) } - if entity.Kind != src.ComponentEntity { + if nodeEntity.Kind != src.ComponentEntity { // if interface, don't do anything else desugaredNodes[nodeName] = node return extraConnections, nil } - _, hasAutoports := entity. - Component. - Directives[compiler.AutoportsDirective] + // everything after this is only for component nodes + component := nodeEntity.Component + + // only if node component uses #autoports + _, hasAutportsDirectory := component.Directives[compiler.AutoportsDirective] - // nothing to desugar - if !hasAutoports && len(node.DIArgs) != 1 { + // autoports and anonymous dependency are everything we need to desugar + if !hasAutportsDirectory && len(node.DIArgs) != 1 { desugaredNodes[nodeName] = node return extraConnections, nil } - // --- anon dep --- - - depArg, ok := node.DIArgs[""] - if ok { - for depParamName, depParam := range entity.Component.Nodes { - depEntity, _, err := scope.Entity(depParam.EntityRef) + // find and desugar anonymous dependency if it's there + anonDepArg, hasAnonDep := node.DIArgs[""] + if hasAnonDep { // this node has anonymous dependency injected + // find name of the dependency in this node's sub-nodes + var depName string + for depParamName, depParam := range nodeEntity.Component.Nodes { + kind, err := scope.GetEntityKind(depParam.EntityRef) if err != nil { panic(err) } - if depEntity.Kind == src.InterfaceEntity { - desugaredDeps := maps.Clone(node.DIArgs) - desugaredDeps[depParamName] = depArg - node = src.Node{ - Directives: node.Directives, - EntityRef: node.EntityRef, - TypeArgs: node.TypeArgs, - DIArgs: desugaredDeps, - Meta: node.Meta, - } - break + if kind == src.InterfaceEntity { + depName = depParamName + break // just take first interface node, only one is allowed } } + + desugaredDIArgs := maps.Clone(node.DIArgs) + desugaredDIArgs[depName] = anonDepArg // actual desugaring + node = src.Node{ // rewrite variable with desugared node + Directives: node.Directives, + EntityRef: node.EntityRef, + TypeArgs: node.TypeArgs, + DIArgs: desugaredDIArgs, + Meta: node.Meta, // original node meta has not just location, but also position + } } - if !hasAutoports { + // no autoports, nothing left to desugar + if !hasAutportsDirectory { desugaredNodes[nodeName] = node return extraConnections, nil } - // --- autoports --- + // autoports are only used for struct-builders + // and those have one type-paremeter, that must be struct + structFields := node.TypeArgs[0].Lit.Struct // it's safe to assume that type-argument is resolved + + // if node of the component with #autoports was used without struct type argument, + // it's an issue in compiler, because that is fact not valid program + if len(structFields) == 0 { + panic("struct-builder has no fields") + } - structFields := node.TypeArgs[0].Lit.Struct + // to desugar autoports, we need to insert virtual component into a program + // that component uses struct_builder runtime function, just like stdlib's struct-builder + // but actually has input ports, that represents type, that is passed as a type-argument + // first, we need to create ports for our virtual component inports := make(map[string]src.Port, len(structFields)) for fieldName, fieldTypeExpr := range structFields { inports[fieldName] = src.Port{ TypeExpr: fieldTypeExpr, + Meta: locOnlyMeta, } } + // there's only one outport in the struct-builder + // and it's type is the same as the type-argument outports := map[string]src.Port{ - "msg": { + "res": { TypeExpr: node.TypeArgs[0], + Meta: locOnlyMeta, }, } - localBuilderFlow := src.Component{ + // now finally create our virtual (native!) component using our virtual ports + virtualComponent := src.Component{ Interface: src.Interface{ - IO: src.IO{In: inports, Out: outports}, + IO: src.IO{In: inports, Out: outports}, + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, } - localBuilderName := fmt.Sprintf("struct_%v", nodeName) + virtualComponentName := fmt.Sprintf("struct_%v", nodeName) - virtualEntities[localBuilderName] = src.Entity{ + virtualEntities[virtualComponentName] = src.Entity{ Kind: src.ComponentEntity, - Component: localBuilderFlow, + Component: virtualComponent, } + // FIXME: HOW DOES IT WORK? WHY DOESN'T IT USES VIRTUAL COMPONENT!?!? desugaredNodes[nodeName] = src.Node{ EntityRef: core.EntityRef{ Pkg: "", diff --git a/internal/compiler/desugarer/struct_selectors.go b/internal/compiler/desugarer/struct_selectors.go index fc66ef67..882f62e3 100644 --- a/internal/compiler/desugarer/struct_selectors.go +++ b/internal/compiler/desugarer/struct_selectors.go @@ -13,11 +13,6 @@ type desugarStructSelectorsResult struct { replace src.Connection } -var selectorNodeRef = core.EntityRef{ - Pkg: "builtin", - Name: "Field", -} - // desugarStructSelectors doesn't generate incoming connections for field node, // it's responsibility of desugarChainConnection. func (d *Desugarer) desugarStructSelectors( @@ -28,6 +23,10 @@ func (d *Desugarer) desugarStructSelectors( desugarStructSelectorsResult, error, ) { + locOnlyMeta := core.Meta{ + Location: normConn.Senders[0].Meta.Location, // FIXME for some reason norm-conn sometimes doesn't have meta + } + d.virtualConstCount++ constName := fmt.Sprintf("__const__%d", d.virtualConstCount) @@ -38,7 +37,12 @@ func (d *Desugarer) desugarStructSelectors( Directives: map[src.Directive][]string{ compiler.BindDirective: {constName}, }, - EntityRef: selectorNodeRef, + EntityRef: core.EntityRef{ + Pkg: "builtin", + Name: "Field", + Meta: locOnlyMeta, + }, + Meta: locOnlyMeta, } // struct selectors are discarded from this point @@ -50,12 +54,15 @@ func (d *Desugarer) desugarStructSelectors( PortAddr: &src.PortAddr{ Node: selectorNodeName, Port: "res", + Meta: locOnlyMeta, }, + Meta: locOnlyMeta, }, }, // and send it to original receiver side Receivers: normConn.Receivers, }, + Meta: locOnlyMeta, } nodesToInsert[selectorNodeName] = selectorNode @@ -83,11 +90,15 @@ var ( func (Desugarer) createSelectorCfgMsg(senderSide src.ConnectionSender) src.Const { result := make([]src.ConstValue, 0, len(senderSide.StructSelector)) + locOnlyMeta := core.Meta{ + Location: senderSide.Meta.Location, + } for _, selector := range senderSide.StructSelector { result = append(result, src.ConstValue{ Message: &src.MsgLiteral{ - Str: compiler.Pointer(selector), + Str: compiler.Pointer(selector), + Meta: locOnlyMeta, }, }) } @@ -97,7 +108,9 @@ func (Desugarer) createSelectorCfgMsg(senderSide src.ConnectionSender) src.Const Value: src.ConstValue{ Message: &src.MsgLiteral{ List: result, + Meta: locOnlyMeta, }, }, + Meta: locOnlyMeta, } } diff --git a/internal/compiler/irgen/irgen.go b/internal/compiler/irgen/irgen.go index 57a31073..e71167ec 100644 --- a/internal/compiler/irgen/irgen.go +++ b/internal/compiler/irgen/irgen.go @@ -32,15 +32,10 @@ func (g Generator) Generate( build src.Build, mainPkgName string, ) (*ir.Program, error) { - scope := src.NewScope(build, core.Location{ + loc := core.Location{ ModRef: build.EntryModRef, Package: mainPkgName, Filename: "", - }) - - result := &ir.Program{ - Connections: map[ir.PortAddr]ir.PortAddr{}, // Changed to 1-1 mapping - Funcs: []ir.FuncCall{}, } rootNodeCtx := nodeContext{ @@ -50,6 +45,7 @@ func (g Generator) Generate( Pkg: "", Name: "Main", }, + Meta: core.Meta{Location: loc}, // it's important to set location for every node, because irgen depends on it }, portsUsage: portsUsage{ in: map[relPortAddr]struct{}{ @@ -61,7 +57,16 @@ func (g Generator) Generate( }, } - g.processNode(rootNodeCtx, scope, result) + result := &ir.Program{ + Connections: map[ir.PortAddr]ir.PortAddr{}, + Funcs: []ir.FuncCall{}, + } + + g.processNode( + rootNodeCtx, + src.NewScope(build, loc), + result, + ) return &ir.Program{ Connections: result.Connections, @@ -74,7 +79,9 @@ func (g Generator) processNode( scope src.Scope, result *ir.Program, ) { - entity, location, err := scope.Entity(nodeCtx.node.EntityRef) + entity, location, err := scope. + Relocate(nodeCtx.node.Meta.Location). + Entity(nodeCtx.node.EntityRef) if err != nil { panic(err) } diff --git a/internal/compiler/irgen/network.go b/internal/compiler/irgen/network.go index f82d30e0..5e701342 100644 --- a/internal/compiler/irgen/network.go +++ b/internal/compiler/irgen/network.go @@ -138,7 +138,7 @@ func (g Generator) processSender( // because only irgen really builds nodes and passes DI args to them depNode, isNodeDep := nodeCtx.node.DIArgs[sender.PortAddr.Node] if isNodeDep && sender.PortAddr.Port == "" { - depComponent, err := scope.GetComponent(depNode.EntityRef) + depComponent, err := scope.Relocate(depNode.Meta.Location).GetComponent(depNode.EntityRef) if err != nil { panic(err) } @@ -185,17 +185,21 @@ func (g Generator) processReceiver( } } - // if sender node is dependency from DI - depNode, ok := nodeCtx.node.DIArgs[receiver.PortAddr.Node] + // if receiver node DI + diArgNode, isDI := nodeCtx.node.DIArgs[receiver.PortAddr.Node] // and if port we are reffering to is an empty string - if ok && receiver.PortAddr.Port == "" { + if isDI && receiver.PortAddr.Port == "" { // we need to find depedency component and use its inport name // this is techically desugaring at irgen level // but it's impossible to desugare before, because only irgen really builds nodes - depComponent, err := scope.GetComponent(depNode.EntityRef) + + depComponent, err := scope. + Relocate(diArgNode.Meta.Location). + GetComponent(diArgNode.EntityRef) if err != nil { panic(err) } + for inport := range depComponent.Interface.IO.In { receiver.PortAddr.Port = inport break diff --git a/internal/compiler/parser/listener_helpers.go b/internal/compiler/parser/listener_helpers.go index 2b0775dd..26d74843 100644 --- a/internal/compiler/parser/listener_helpers.go +++ b/internal/compiler/parser/listener_helpers.go @@ -1179,11 +1179,26 @@ func (s *treeShapeListener) parseCompDef(actx generated.ICompDefContext) (src.En } body := actx.CompBody() + + meta := core.Meta{ + Text: actx.GetText(), + Start: core.Position{ + Line: actx.GetStart().GetLine(), + Column: actx.GetStart().GetColumn(), + }, + Stop: core.Position{ + Line: actx.GetStop().GetLine(), + Column: actx.GetStop().GetColumn(), + }, + Location: s.loc, + } + if body == nil { return src.Entity{ Kind: src.ComponentEntity, Component: src.Component{ Interface: parsedInterfaceDef, + Meta: meta, }, }, nil } @@ -1205,16 +1220,15 @@ func (s *treeShapeListener) parseCompDef(actx generated.ICompDefContext) (src.En Component: src.Component{ Interface: parsedInterfaceDef, Net: parsedConnections, + Meta: meta, }, }, nil } - var parsedNodes map[string]src.Node - v, err := s.parseNodes(nodesDef.CompNodesDefBody(), true) + parsedNodes, err := s.parseNodes(nodesDef.CompNodesDefBody(), true) if err != nil { return src.Entity{}, err } - parsedNodes = v return src.Entity{ Kind: src.ComponentEntity, @@ -1222,18 +1236,7 @@ func (s *treeShapeListener) parseCompDef(actx generated.ICompDefContext) (src.En Interface: parsedInterfaceDef, Nodes: parsedNodes, Net: parsedConnections, - Meta: core.Meta{ - Text: actx.GetText(), - Start: core.Position{ - Line: actx.GetStart().GetLine(), - Column: actx.GetStart().GetColumn(), - }, - Stop: core.Position{ - Line: actx.GetStop().GetLine(), - Column: actx.GetStop().GetColumn(), - }, - Location: s.loc, - }, + Meta: meta, }, }, nil } diff --git a/internal/runtime/funcs/int_mod.go b/internal/runtime/funcs/int_mod.go index 08273fc9..63ff4409 100644 --- a/internal/runtime/funcs/int_mod.go +++ b/internal/runtime/funcs/int_mod.go @@ -9,7 +9,7 @@ import ( type intMod struct{} func (intMod) Create(io runtime.IO, _ runtime.Msg) (func(ctx context.Context), error) { - numIn, err := io.In.Single("left") // numerator + leftIn, err := io.In.Single("left") // numerator if err != nil { return nil, err } @@ -19,14 +19,14 @@ func (intMod) Create(io runtime.IO, _ runtime.Msg) (func(ctx context.Context), e return nil, err } - resOut, err := io.Out.Single("res") + resOut, err := io.Out.Single("res") // modulo if err != nil { return nil, err } return func(ctx context.Context) { for { - numMsg, ok := numIn.Receive(ctx) + numMsg, ok := leftIn.Receive(ctx) if !ok { return } @@ -36,12 +36,9 @@ func (intMod) Create(io runtime.IO, _ runtime.Msg) (func(ctx context.Context), e return } - if !resOut.Send( - ctx, - runtime.NewIntMsg( - numMsg.Int()%denMsg.Int(), - ), - ) { + num := numMsg.Int() + den := denMsg.Int() + if !resOut.Send(ctx, runtime.NewIntMsg(num%den)) { return } } diff --git a/internal/runtime/funcs/new_v2.go b/internal/runtime/funcs/new_v2.go index ddb475e4..8df73ae6 100644 --- a/internal/runtime/funcs/new_v2.go +++ b/internal/runtime/funcs/new_v2.go @@ -14,7 +14,7 @@ func (c newV2) Create(io runtime.IO, cfg runtime.Msg) (func(ctx context.Context) return nil, err } - resOut, err := io.Out.Single("data") + resOut, err := io.Out.Single("res") if err != nil { return nil, err } @@ -29,4 +29,4 @@ func (c newV2) Create(io runtime.IO, cfg runtime.Msg) (func(ctx context.Context) } } }, nil -} \ No newline at end of file +} diff --git a/internal/runtime/message.go b/internal/runtime/message.go index b8efb4a5..4439dc9f 100644 --- a/internal/runtime/message.go +++ b/internal/runtime/message.go @@ -35,16 +35,22 @@ type Msg interface { type internalMsg struct{} -func (internalMsg) String() string { panic("unexpected method call on internal message") } -func (internalMsg) Bool() bool { panic("unexpected method call on internal message") } -func (internalMsg) Int() int64 { panic("unexpected method call on internal message") } -func (internalMsg) Float() float64 { panic("unexpected method call on internal message") } -func (internalMsg) Str() string { panic("unexpected method call on internal message") } -func (internalMsg) List() []Msg { panic("unexpected method call on internal message") } -func (internalMsg) Dict() map[string]Msg { panic("unexpected method call on internal message") } -func (internalMsg) Struct() StructMsg { panic("unexpected method call on internal message") } -func (internalMsg) Union() UnionMsg { panic("unexpected method call on internal message") } -func (internalMsg) Equal(other Msg) bool { panic("unexpected method call on internal message") } +func (internalMsg) String() string { panic("unexpected String method call on internal message type") } +func (internalMsg) Bool() bool { panic("unexpected Bool method call on internal message type") } +func (internalMsg) Int() int64 { panic("unexpected Int method call on internal message type") } +func (internalMsg) Float() float64 { panic("unexpected Float method call on internal message type") } +func (internalMsg) Str() string { panic("unexpected Str method call on internal message type") } +func (internalMsg) List() []Msg { panic("unexpected List method call on internal message type") } +func (internalMsg) Dict() map[string]Msg { + panic("unexpected Dict method call on internal message type") +} +func (internalMsg) Struct() StructMsg { + panic("unexpected Struct method call on internal message type") +} +func (internalMsg) Union() UnionMsg { panic("unexpected Union method call on internal message type") } +func (internalMsg) Equal(other Msg) bool { + panic("unexpected Equal method call on internal message type") +} // Bool From bc697cf1c3e0bee5cde85f930da1e3f8f4415964 Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Sun, 15 Dec 2024 14:54:02 +0500 Subject: [PATCH 24/28] fix(desugarer): do not reset counters, because that lead to overwriting entity in the scope, because constants are created in the root package space without prefixes in their names --- .vscode/settings.json | 7 +- internal/compiler/desugarer/desugarer.go | 115 ++++++++++---------- internal/compiler/desugarer/network_test.go | 6 +- internal/runtime/message.go | 2 +- internal/runtime/program.go | 4 +- std/builtin/routers.neva | 28 ++--- 6 files changed, 85 insertions(+), 77 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 52c18773..28a5349c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -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" + } + } } diff --git a/internal/compiler/desugarer/desugarer.go b/internal/compiler/desugarer/desugarer.go index e114e270..2bf7d02a 100644 --- a/internal/compiler/desugarer/desugarer.go +++ b/internal/compiler/desugarer/desugarer.go @@ -9,7 +9,7 @@ import ( "github.com/nevalang/neva/pkg" ) -// Desugarer is NOT concurrent safe and must be used in single thread +// Desugarer is NOT thread safe and must be used in single thread type Desugarer struct { virtualSelectorsCount uint64 ternaryCounter uint64 @@ -158,7 +158,8 @@ func (d *Desugarer) desugarFile( return src.File{}, fmt.Errorf("desugar entity %s: %w", entityName, err) } - d.resetCounters() + // FIXMEL: https://github.com/nevalang/neva/issues/808 + // d.resetCounters() desugaredEntities[entityName] = entityResult.entity @@ -228,60 +229,62 @@ func (d *Desugarer) desugarEntity( }, nil } -func (d *Desugarer) resetCounters() { - d.virtualSelectorsCount = 0 - d.ternaryCounter = 0 - d.switchCounter = 0 - d.virtualLocksCounter = 0 - d.virtualEmittersCount = 0 - d.virtualConstCount = 0 - d.virtualTriggersCount = 0 - d.fanOutCounter = 0 - d.fanInCounter = 0 - d.rangeCounter = 0 - // - d.addCounter = 0 - d.subCounter = 0 - d.mulCounter = 0 - d.divCounter = 0 - d.modCounter = 0 - d.powCounter = 0 - // - d.eqCounter = 0 - d.neCounter = 0 - d.gtCounter = 0 - d.ltCounter = 0 - d.geCounter = 0 - d.leCounter = 0 - // - d.andCounter = 0 - d.orCounter = 0 - d.bitAndCounter = 0 - d.bitOrCounter = 0 - d.bitXorCounter = 0 - d.bitLshCounter = 0 - d.bitRshCounter = 0 - d.mulCounter = 0 - d.divCounter = 0 - d.modCounter = 0 - d.powCounter = 0 - // - d.eqCounter = 0 - d.neCounter = 0 - d.gtCounter = 0 - d.ltCounter = 0 - d.geCounter = 0 - d.leCounter = 0 - // - d.andCounter = 0 - d.orCounter = 0 - // - d.bitAndCounter = 0 - d.bitOrCounter = 0 - d.bitXorCounter = 0 - d.bitLshCounter = 0 - d.bitRshCounter = 0 -} +// FIXME: https://github.com/nevalang/neva/issues/808 +// Do NOT use this method until issue is fixed +// func (d *Desugarer) resetCounters() { +// d.virtualSelectorsCount = 0 +// d.ternaryCounter = 0 +// d.switchCounter = 0 +// d.virtualLocksCounter = 0 +// d.virtualEmittersCount = 0 +// d.virtualConstCount = 0 +// d.virtualTriggersCount = 0 +// d.fanOutCounter = 0 +// d.fanInCounter = 0 +// d.rangeCounter = 0 +// // +// d.addCounter = 0 +// d.subCounter = 0 +// d.mulCounter = 0 +// d.divCounter = 0 +// d.modCounter = 0 +// d.powCounter = 0 +// // +// d.eqCounter = 0 +// d.neCounter = 0 +// d.gtCounter = 0 +// d.ltCounter = 0 +// d.geCounter = 0 +// d.leCounter = 0 +// // +// d.andCounter = 0 +// d.orCounter = 0 +// d.bitAndCounter = 0 +// d.bitOrCounter = 0 +// d.bitXorCounter = 0 +// d.bitLshCounter = 0 +// d.bitRshCounter = 0 +// d.mulCounter = 0 +// d.divCounter = 0 +// d.modCounter = 0 +// d.powCounter = 0 +// // +// d.eqCounter = 0 +// d.neCounter = 0 +// d.gtCounter = 0 +// d.ltCounter = 0 +// d.geCounter = 0 +// d.leCounter = 0 +// // +// d.andCounter = 0 +// d.orCounter = 0 +// // +// d.bitAndCounter = 0 +// d.bitOrCounter = 0 +// d.bitXorCounter = 0 +// d.bitLshCounter = 0 +// d.bitRshCounter = 0 +// } func New() Desugarer { return Desugarer{} diff --git a/internal/compiler/desugarer/network_test.go b/internal/compiler/desugarer/network_test.go index 707924cc..13ede0e4 100644 --- a/internal/compiler/desugarer/network_test.go +++ b/internal/compiler/desugarer/network_test.go @@ -101,7 +101,7 @@ func TestDesugarNetwork(t *testing.T) { }, Receivers: []src.ConnectionReceiver{ { - PortAddr: &src.PortAddr{Node: "__fanIn__1", Port: "data", Idx: compiler.Pointer(uint8(0))}, + PortAddr: &src.PortAddr{Node: "__fan_in__1", Port: "data", Idx: compiler.Pointer(uint8(0))}, }, }, }, @@ -115,7 +115,7 @@ func TestDesugarNetwork(t *testing.T) { }, Receivers: []src.ConnectionReceiver{ { - PortAddr: &src.PortAddr{Node: "__fanIn__1", Port: "data", Idx: compiler.Pointer(uint8(1))}, + PortAddr: &src.PortAddr{Node: "__fan_in__1", Port: "data", Idx: compiler.Pointer(uint8(1))}, }, }, }, @@ -124,7 +124,7 @@ func TestDesugarNetwork(t *testing.T) { Normal: &src.NormalConnection{ Senders: []src.ConnectionSender{ { - PortAddr: &src.PortAddr{Node: "__fanIn__1", Port: "res"}, + PortAddr: &src.PortAddr{Node: "__fan_in__1", Port: "res"}, }, }, Receivers: []src.ConnectionReceiver{ diff --git a/internal/runtime/message.go b/internal/runtime/message.go index 4439dc9f..c9d3c99e 100644 --- a/internal/runtime/message.go +++ b/internal/runtime/message.go @@ -28,7 +28,7 @@ type Msg interface { Struct() StructMsg Union() UnionMsg - Equal(other Msg) bool + Equal(Msg) bool } // Internal diff --git a/internal/runtime/program.go b/internal/runtime/program.go index c1ccbfe5..8493623b 100644 --- a/internal/runtime/program.go +++ b/internal/runtime/program.go @@ -185,7 +185,7 @@ func (a ArrayInport) ReceiveAll(ctx context.Context, f func(idx int, msg Msg) bo select { case <-ctx.Done(): success = false - case v := <-a.chans[idx]: + case received := <-a.chans[idx]: index := uint8(idx) msg := a.interceptor.Received( PortSlotAddr{ @@ -195,7 +195,7 @@ func (a ArrayInport) ReceiveAll(ctx context.Context, f func(idx int, msg Msg) bo }, Index: &index, }, - v.Msg, + received.Msg, ) resultChan <- f(idx, msg) } diff --git a/std/builtin/routers.neva b/std/builtin/routers.neva index bb7842d6..f2dcedd8 100644 --- a/std/builtin/routers.neva +++ b/std/builtin/routers.neva @@ -1,24 +1,24 @@ -// `Cond` is like `If`, but also allows to route data based on a condition. -#extern(cond) -pub def Cond(data T, if bool) (then T, else T) - -// Switch is a more powerful version of `If` that handles multiple cases. -// Just like `If`, it is used for data routing. -// If you need mapping, use Match or Select instead. -#extern(switch_router) -pub def Switch(data T, [case] T) ([case] T, else T) - // Lock allows to defer receiving until some sending happens. #extern(lock) pub def Lock(sig any, data T) (data T) +// FanIn merges several sources of data into single one. +// It makes sure order of incoming messages is respected. +#extern(fan_in) +pub def FanIn([data] T) (res T) + // FanOut is used to broadcast a message from one sender to multiple receivers. // You should use multiple receivers syntax `-> [...]` instead. // Multiple receivers is a syntax sugar over explicit FanOut. #extern(fan_out) pub def FanOut(data T) ([data] T) -// FanIn merges several sources of data into single one. -// It makes sure order of incoming messages is respected. -#extern(fan_in) -pub def FanIn([data] T) (res T) \ No newline at end of file +// `Cond` is like `If`, but also allows to route data based on a condition. +#extern(cond) +pub def Cond(data T, if bool) (then T, else T) + +// Switch is a more powerful version of `If` that handles multiple cases. +// Just like `If`, it is used for data routing. +// If you need mapping, use Match or Select instead. +#extern(switch_router) +pub def Switch(data T, [case] T) ([case] T, else T) From 3df29ae62177c518a028e54666eb1e9b95b408af Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Sun, 15 Dec 2024 14:58:52 +0500 Subject: [PATCH 25/28] fix(std:builtin): filter/split - unpack data before sending to predicate (lack of type checking for DI args made us able to write this code) --- std/builtin/streams.neva | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/std/builtin/streams.neva b/std/builtin/streams.neva index 8c920616..85f8b4f7 100644 --- a/std/builtin/streams.neva +++ b/std/builtin/streams.neva @@ -21,11 +21,6 @@ pub interface IPortReducer(stream) (T) // === Iterators === -// These constants are used for binding by Field. -const dataPath list = ['data'] -const lastPath list = ['last'] -const idxPath list = ['idx'] - // --- Map --- // IMapHandler is a dependency for Map. @@ -63,11 +58,13 @@ pub def Filter(data stream) (res stream) { split:then -> s2l -> l2s -> :res } +// Split splits a stream into two streams based on a predicate. +// Notice that it does not modifies stream item indexes and last flag. pub def Split(data stream) (then stream, else stream) { cond Cond> predicate IPredicate --- - :data -> [cond:data, predicate] + :data -> [cond:data, .data -> predicate] predicate -> cond:if cond:then -> :then cond:else -> :else From adad78f06a5206562215f1d0be6eccc78474963d Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Sun, 15 Dec 2024 15:18:09 +0500 Subject: [PATCH 26/28] fix(desugarer): unit tests --- internal/compiler/desugarer/network.go | 6 ++---- internal/compiler/desugarer/network_test.go | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/internal/compiler/desugarer/network.go b/internal/compiler/desugarer/network.go index fca0cf97..c392b216 100644 --- a/internal/compiler/desugarer/network.go +++ b/internal/compiler/desugarer/network.go @@ -1171,13 +1171,11 @@ func (d *Desugarer) desugarFanIn( scope Scope, nodes map[string]src.Node, ) ([]src.Connection, error) { - locOnlyMeta := core.Meta{ - Location: *scope.Location(), - } + locOnlyMeta := normConn.Senders[0].Meta // FIXME for some reason normConn.Meta sometimes empty // 1. create fan-in node with unique name and insert into nodes d.fanInCounter++ - fanInNodeName := fmt.Sprintf("__fanIn__%d", d.fanInCounter) + fanInNodeName := fmt.Sprintf("__fan_in__%d", d.fanInCounter) nodesToInsert[fanInNodeName] = src.Node{ EntityRef: core.EntityRef{ Pkg: "builtin", diff --git a/internal/compiler/desugarer/network_test.go b/internal/compiler/desugarer/network_test.go index 13ede0e4..b9fc3429 100644 --- a/internal/compiler/desugarer/network_test.go +++ b/internal/compiler/desugarer/network_test.go @@ -137,7 +137,7 @@ func TestDesugarNetwork(t *testing.T) { }, constsToInsert: map[string]src.Const{}, nodesToInsert: map[string]src.Node{ - "__fanIn__1": { + "__fan_in__1": { EntityRef: core.EntityRef{Pkg: "builtin", Name: "FanIn"}, }, }, From 330a5d28e0cad346fdcbf1b79e0f35a96f849655 Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Sun, 15 Dec 2024 15:19:46 +0500 Subject: [PATCH 27/28] feat(version): bump to 029 everywhere --- docs/book/program_structure.md | 6 +++--- docs/tutorial.md | 4 ++-- e2e/99_bottles_verbose/neva.yml | 2 +- e2e/add_nums_from_stdin_naive/neva.yml | 2 +- e2e/add_nums_from_stdin_with_default_any/neva.yml | 2 +- e2e/add_nums_from_stdin_with_err_handling/neva.yml | 2 +- e2e/add_nums_from_stdin_with_multuple_senders/neva.yml | 2 +- e2e/add_nums_from_stdin_with_sub_components/neva.yml | 2 +- e2e/add_nums_verbose/neva.yml | 2 +- e2e/array_inport_holes/neva.yml | 2 +- e2e/array_outport_holes/neva.yml | 2 +- e2e/binary_operators/arithmetic/add_floats/neva.yml | 2 +- e2e/binary_operators/arithmetic/add_ints/neva.yml | 2 +- e2e/binary_operators/arithmetic/add_strings/neva.yml | 2 +- e2e/binary_operators/arithmetic/divide_floats/neva.yml | 2 +- e2e/binary_operators/arithmetic/divide_ints/neva.yml | 2 +- e2e/binary_operators/arithmetic/modulo/neva.yml | 2 +- e2e/binary_operators/arithmetic/multiply_floats/neva.yml | 2 +- e2e/binary_operators/arithmetic/multiply_ints/neva.yml | 2 +- e2e/binary_operators/arithmetic/power/neva.yml | 2 +- e2e/binary_operators/arithmetic/subtract_floats/neva.yml | 2 +- e2e/binary_operators/arithmetic/subtract_ints/neva.yml | 2 +- e2e/binary_operators/bitwise/and/neva.yml | 2 +- e2e/binary_operators/bitwise/left_shift/neva.yml | 2 +- e2e/binary_operators/bitwise/or/neva.yml | 2 +- e2e/binary_operators/bitwise/right_shift/neva.yml | 2 +- e2e/binary_operators/bitwise/xor/neva.yml | 2 +- e2e/binary_operators/comparison/equal/neva.yml | 2 +- e2e/binary_operators/comparison/greater_int/neva.yml | 2 +- .../comparison/greater_or_equal_int/neva.yml | 2 +- e2e/binary_operators/comparison/less_int/neva.yml | 2 +- e2e/binary_operators/comparison/less_or_equal_int/neva.yml | 2 +- e2e/binary_operators/comparison/not_equal/neva.yml | 2 +- e2e/binary_operators/logical/and/neva.yml | 2 +- e2e/binary_operators/logical/or/neva.yml | 2 +- e2e/cli_new/neva.yml | 2 +- e2e/comments/neva.yml | 2 +- e2e/compiler_error_unused_outport/neva.yml | 2 +- e2e/const_refs_verbose/neva.yml | 2 +- e2e/div_test/neva.yml | 2 +- e2e/do_nothing_verbose/neva.yml | 2 +- e2e/duplicate_receiver/neva.yml | 2 +- e2e/duplicate_sender/neva.yml | 2 +- e2e/echo_verbose/neva.yml | 2 +- e2e/enums_verbose/neva.yml | 2 +- e2e/float_const_with_int_lit/neva.yml | 2 +- e2e/for_loop_over_list_verbose/neva.yml | 2 +- e2e/for_with_range_and_if/neva.yml | 2 +- e2e/hello_world_verbose/neva.yml | 2 +- e2e/hello_world_with_const_sender/neva.yml | 2 +- e2e/hello_world_with_implicit_any/neva.yml | 2 +- e2e/hello_world_with_literal_sender/neva.yml | 2 +- e2e/hello_world_with_then_connection/neva.yml | 2 +- e2e/hello_world_with_unnamed_node/neva.yml | 2 +- e2e/inc_test/neva.yml | 2 +- e2e/incompat_comp_type_arg/neva.yml | 2 +- e2e/incompat_types_with_untyped_port/neva.yml | 2 +- e2e/interface_anonymous/neva.yml | 2 +- e2e/interface_verbose/neva.yml | 2 +- e2e/interface_with_imports/neva.yml | 2 +- e2e/list_with_neg_nums/neva.yml | 2 +- e2e/local_imports/neva.yml | 2 +- e2e/map_list_verbose/neva.yml | 2 +- e2e/multiply_numbers/neva.yml | 2 +- e2e/non_unique_fan_in/neva.yml | 2 +- e2e/non_unique_fan_out/neva.yml | 2 +- e2e/order_dependend_with_arr_inport/neva.yml | 2 +- e2e/print_float/neva.yml | 2 +- e2e/regex_submatch_verbose/neva.yml | 2 +- e2e/run_cli_not_from_module_root/neva.yml | 2 +- e2e/simple_fan_out/neva.yml | 2 +- e2e/slow_iteration_with_for/neva.yml | 2 +- e2e/slow_iteration_with_map/neva.yml | 2 +- e2e/struct_builder_verbose/neva.yml | 2 +- e2e/struct_builder_with_sugar/neva.yml | 2 +- e2e/struct_selector_on_port_addr/neva.yml | 2 +- e2e/struct_selector_verbose/neva.yml | 2 +- e2e/struct_selector_with_more_sugar/neva.yml | 2 +- e2e/struct_selector_with_sugar/neva.yml | 2 +- e2e/type_expr_with_imported_type_arg/neva.yml | 2 +- examples/neva.yml | 2 +- internal/builder/tests/intergration_test.go | 4 ++-- internal/builder/tests/testmod/neva.yml | 2 +- std/neva.yml | 2 +- 84 files changed, 88 insertions(+), 88 deletions(-) diff --git a/docs/book/program_structure.md b/docs/book/program_structure.md index f0054159..68fedf40 100644 --- a/docs/book/program_structure.md +++ b/docs/book/program_structure.md @@ -36,10 +36,10 @@ 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 @@ -51,7 +51,7 @@ The `deps` field is a map where each dependency has an alias. When adding depend > 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 diff --git a/docs/tutorial.md b/docs/tutorial.md index 156b8aca..c6bacf89 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -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! @@ -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. diff --git a/e2e/99_bottles_verbose/neva.yml b/e2e/99_bottles_verbose/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/99_bottles_verbose/neva.yml +++ b/e2e/99_bottles_verbose/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/add_nums_from_stdin_naive/neva.yml b/e2e/add_nums_from_stdin_naive/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/add_nums_from_stdin_naive/neva.yml +++ b/e2e/add_nums_from_stdin_naive/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/add_nums_from_stdin_with_default_any/neva.yml b/e2e/add_nums_from_stdin_with_default_any/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/add_nums_from_stdin_with_default_any/neva.yml +++ b/e2e/add_nums_from_stdin_with_default_any/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/add_nums_from_stdin_with_err_handling/neva.yml b/e2e/add_nums_from_stdin_with_err_handling/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/add_nums_from_stdin_with_err_handling/neva.yml +++ b/e2e/add_nums_from_stdin_with_err_handling/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/add_nums_from_stdin_with_multuple_senders/neva.yml b/e2e/add_nums_from_stdin_with_multuple_senders/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/add_nums_from_stdin_with_multuple_senders/neva.yml +++ b/e2e/add_nums_from_stdin_with_multuple_senders/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/add_nums_from_stdin_with_sub_components/neva.yml b/e2e/add_nums_from_stdin_with_sub_components/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/add_nums_from_stdin_with_sub_components/neva.yml +++ b/e2e/add_nums_from_stdin_with_sub_components/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/add_nums_verbose/neva.yml b/e2e/add_nums_verbose/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/add_nums_verbose/neva.yml +++ b/e2e/add_nums_verbose/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/array_inport_holes/neva.yml b/e2e/array_inport_holes/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/array_inport_holes/neva.yml +++ b/e2e/array_inport_holes/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/array_outport_holes/neva.yml b/e2e/array_outport_holes/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/array_outport_holes/neva.yml +++ b/e2e/array_outport_holes/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/arithmetic/add_floats/neva.yml b/e2e/binary_operators/arithmetic/add_floats/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/arithmetic/add_floats/neva.yml +++ b/e2e/binary_operators/arithmetic/add_floats/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/arithmetic/add_ints/neva.yml b/e2e/binary_operators/arithmetic/add_ints/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/arithmetic/add_ints/neva.yml +++ b/e2e/binary_operators/arithmetic/add_ints/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/arithmetic/add_strings/neva.yml b/e2e/binary_operators/arithmetic/add_strings/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/arithmetic/add_strings/neva.yml +++ b/e2e/binary_operators/arithmetic/add_strings/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/arithmetic/divide_floats/neva.yml b/e2e/binary_operators/arithmetic/divide_floats/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/arithmetic/divide_floats/neva.yml +++ b/e2e/binary_operators/arithmetic/divide_floats/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/arithmetic/divide_ints/neva.yml b/e2e/binary_operators/arithmetic/divide_ints/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/arithmetic/divide_ints/neva.yml +++ b/e2e/binary_operators/arithmetic/divide_ints/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/arithmetic/modulo/neva.yml b/e2e/binary_operators/arithmetic/modulo/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/arithmetic/modulo/neva.yml +++ b/e2e/binary_operators/arithmetic/modulo/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/arithmetic/multiply_floats/neva.yml b/e2e/binary_operators/arithmetic/multiply_floats/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/arithmetic/multiply_floats/neva.yml +++ b/e2e/binary_operators/arithmetic/multiply_floats/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/arithmetic/multiply_ints/neva.yml b/e2e/binary_operators/arithmetic/multiply_ints/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/arithmetic/multiply_ints/neva.yml +++ b/e2e/binary_operators/arithmetic/multiply_ints/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/arithmetic/power/neva.yml b/e2e/binary_operators/arithmetic/power/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/arithmetic/power/neva.yml +++ b/e2e/binary_operators/arithmetic/power/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/arithmetic/subtract_floats/neva.yml b/e2e/binary_operators/arithmetic/subtract_floats/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/arithmetic/subtract_floats/neva.yml +++ b/e2e/binary_operators/arithmetic/subtract_floats/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/arithmetic/subtract_ints/neva.yml b/e2e/binary_operators/arithmetic/subtract_ints/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/arithmetic/subtract_ints/neva.yml +++ b/e2e/binary_operators/arithmetic/subtract_ints/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/bitwise/and/neva.yml b/e2e/binary_operators/bitwise/and/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/bitwise/and/neva.yml +++ b/e2e/binary_operators/bitwise/and/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/bitwise/left_shift/neva.yml b/e2e/binary_operators/bitwise/left_shift/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/bitwise/left_shift/neva.yml +++ b/e2e/binary_operators/bitwise/left_shift/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/bitwise/or/neva.yml b/e2e/binary_operators/bitwise/or/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/bitwise/or/neva.yml +++ b/e2e/binary_operators/bitwise/or/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/bitwise/right_shift/neva.yml b/e2e/binary_operators/bitwise/right_shift/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/bitwise/right_shift/neva.yml +++ b/e2e/binary_operators/bitwise/right_shift/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/bitwise/xor/neva.yml b/e2e/binary_operators/bitwise/xor/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/bitwise/xor/neva.yml +++ b/e2e/binary_operators/bitwise/xor/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/comparison/equal/neva.yml b/e2e/binary_operators/comparison/equal/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/comparison/equal/neva.yml +++ b/e2e/binary_operators/comparison/equal/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/comparison/greater_int/neva.yml b/e2e/binary_operators/comparison/greater_int/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/comparison/greater_int/neva.yml +++ b/e2e/binary_operators/comparison/greater_int/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/comparison/greater_or_equal_int/neva.yml b/e2e/binary_operators/comparison/greater_or_equal_int/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/comparison/greater_or_equal_int/neva.yml +++ b/e2e/binary_operators/comparison/greater_or_equal_int/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/comparison/less_int/neva.yml b/e2e/binary_operators/comparison/less_int/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/comparison/less_int/neva.yml +++ b/e2e/binary_operators/comparison/less_int/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/comparison/less_or_equal_int/neva.yml b/e2e/binary_operators/comparison/less_or_equal_int/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/comparison/less_or_equal_int/neva.yml +++ b/e2e/binary_operators/comparison/less_or_equal_int/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/comparison/not_equal/neva.yml b/e2e/binary_operators/comparison/not_equal/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/comparison/not_equal/neva.yml +++ b/e2e/binary_operators/comparison/not_equal/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/logical/and/neva.yml b/e2e/binary_operators/logical/and/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/logical/and/neva.yml +++ b/e2e/binary_operators/logical/and/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/binary_operators/logical/or/neva.yml b/e2e/binary_operators/logical/or/neva.yml index 58b83c7c..f3cfe97d 100644 --- a/e2e/binary_operators/logical/or/neva.yml +++ b/e2e/binary_operators/logical/or/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/cli_new/neva.yml b/e2e/cli_new/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/cli_new/neva.yml +++ b/e2e/cli_new/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/comments/neva.yml b/e2e/comments/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/comments/neva.yml +++ b/e2e/comments/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/compiler_error_unused_outport/neva.yml b/e2e/compiler_error_unused_outport/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/compiler_error_unused_outport/neva.yml +++ b/e2e/compiler_error_unused_outport/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/const_refs_verbose/neva.yml b/e2e/const_refs_verbose/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/const_refs_verbose/neva.yml +++ b/e2e/const_refs_verbose/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/div_test/neva.yml b/e2e/div_test/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/div_test/neva.yml +++ b/e2e/div_test/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/do_nothing_verbose/neva.yml b/e2e/do_nothing_verbose/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/do_nothing_verbose/neva.yml +++ b/e2e/do_nothing_verbose/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/duplicate_receiver/neva.yml b/e2e/duplicate_receiver/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/duplicate_receiver/neva.yml +++ b/e2e/duplicate_receiver/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/duplicate_sender/neva.yml b/e2e/duplicate_sender/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/duplicate_sender/neva.yml +++ b/e2e/duplicate_sender/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/echo_verbose/neva.yml b/e2e/echo_verbose/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/echo_verbose/neva.yml +++ b/e2e/echo_verbose/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/enums_verbose/neva.yml b/e2e/enums_verbose/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/enums_verbose/neva.yml +++ b/e2e/enums_verbose/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/float_const_with_int_lit/neva.yml b/e2e/float_const_with_int_lit/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/float_const_with_int_lit/neva.yml +++ b/e2e/float_const_with_int_lit/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/for_loop_over_list_verbose/neva.yml b/e2e/for_loop_over_list_verbose/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/for_loop_over_list_verbose/neva.yml +++ b/e2e/for_loop_over_list_verbose/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/for_with_range_and_if/neva.yml b/e2e/for_with_range_and_if/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/for_with_range_and_if/neva.yml +++ b/e2e/for_with_range_and_if/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/hello_world_verbose/neva.yml b/e2e/hello_world_verbose/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/hello_world_verbose/neva.yml +++ b/e2e/hello_world_verbose/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/hello_world_with_const_sender/neva.yml b/e2e/hello_world_with_const_sender/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/hello_world_with_const_sender/neva.yml +++ b/e2e/hello_world_with_const_sender/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/hello_world_with_implicit_any/neva.yml b/e2e/hello_world_with_implicit_any/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/hello_world_with_implicit_any/neva.yml +++ b/e2e/hello_world_with_implicit_any/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/hello_world_with_literal_sender/neva.yml b/e2e/hello_world_with_literal_sender/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/hello_world_with_literal_sender/neva.yml +++ b/e2e/hello_world_with_literal_sender/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/hello_world_with_then_connection/neva.yml b/e2e/hello_world_with_then_connection/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/hello_world_with_then_connection/neva.yml +++ b/e2e/hello_world_with_then_connection/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/hello_world_with_unnamed_node/neva.yml b/e2e/hello_world_with_unnamed_node/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/hello_world_with_unnamed_node/neva.yml +++ b/e2e/hello_world_with_unnamed_node/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/inc_test/neva.yml b/e2e/inc_test/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/inc_test/neva.yml +++ b/e2e/inc_test/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/incompat_comp_type_arg/neva.yml b/e2e/incompat_comp_type_arg/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/incompat_comp_type_arg/neva.yml +++ b/e2e/incompat_comp_type_arg/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/incompat_types_with_untyped_port/neva.yml b/e2e/incompat_types_with_untyped_port/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/incompat_types_with_untyped_port/neva.yml +++ b/e2e/incompat_types_with_untyped_port/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/interface_anonymous/neva.yml b/e2e/interface_anonymous/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/interface_anonymous/neva.yml +++ b/e2e/interface_anonymous/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/interface_verbose/neva.yml b/e2e/interface_verbose/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/interface_verbose/neva.yml +++ b/e2e/interface_verbose/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/interface_with_imports/neva.yml b/e2e/interface_with_imports/neva.yml index 23a78e8a..62b66f04 100644 --- a/e2e/interface_with_imports/neva.yml +++ b/e2e/interface_with_imports/neva.yml @@ -1,4 +1,4 @@ -neva: 0.28.2 +neva: 0.29.0 deps: github.com/nevalang/x: path: github.com/nevalang/x diff --git a/e2e/list_with_neg_nums/neva.yml b/e2e/list_with_neg_nums/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/list_with_neg_nums/neva.yml +++ b/e2e/list_with_neg_nums/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/local_imports/neva.yml b/e2e/local_imports/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/local_imports/neva.yml +++ b/e2e/local_imports/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/map_list_verbose/neva.yml b/e2e/map_list_verbose/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/map_list_verbose/neva.yml +++ b/e2e/map_list_verbose/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/multiply_numbers/neva.yml b/e2e/multiply_numbers/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/multiply_numbers/neva.yml +++ b/e2e/multiply_numbers/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/non_unique_fan_in/neva.yml b/e2e/non_unique_fan_in/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/non_unique_fan_in/neva.yml +++ b/e2e/non_unique_fan_in/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/non_unique_fan_out/neva.yml b/e2e/non_unique_fan_out/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/non_unique_fan_out/neva.yml +++ b/e2e/non_unique_fan_out/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/order_dependend_with_arr_inport/neva.yml b/e2e/order_dependend_with_arr_inport/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/order_dependend_with_arr_inport/neva.yml +++ b/e2e/order_dependend_with_arr_inport/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/print_float/neva.yml b/e2e/print_float/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/print_float/neva.yml +++ b/e2e/print_float/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/regex_submatch_verbose/neva.yml b/e2e/regex_submatch_verbose/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/regex_submatch_verbose/neva.yml +++ b/e2e/regex_submatch_verbose/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/run_cli_not_from_module_root/neva.yml b/e2e/run_cli_not_from_module_root/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/run_cli_not_from_module_root/neva.yml +++ b/e2e/run_cli_not_from_module_root/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/simple_fan_out/neva.yml b/e2e/simple_fan_out/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/simple_fan_out/neva.yml +++ b/e2e/simple_fan_out/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/slow_iteration_with_for/neva.yml b/e2e/slow_iteration_with_for/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/slow_iteration_with_for/neva.yml +++ b/e2e/slow_iteration_with_for/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/slow_iteration_with_map/neva.yml b/e2e/slow_iteration_with_map/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/slow_iteration_with_map/neva.yml +++ b/e2e/slow_iteration_with_map/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/struct_builder_verbose/neva.yml b/e2e/struct_builder_verbose/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/struct_builder_verbose/neva.yml +++ b/e2e/struct_builder_verbose/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/struct_builder_with_sugar/neva.yml b/e2e/struct_builder_with_sugar/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/struct_builder_with_sugar/neva.yml +++ b/e2e/struct_builder_with_sugar/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/struct_selector_on_port_addr/neva.yml b/e2e/struct_selector_on_port_addr/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/struct_selector_on_port_addr/neva.yml +++ b/e2e/struct_selector_on_port_addr/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/struct_selector_verbose/neva.yml b/e2e/struct_selector_verbose/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/struct_selector_verbose/neva.yml +++ b/e2e/struct_selector_verbose/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/struct_selector_with_more_sugar/neva.yml b/e2e/struct_selector_with_more_sugar/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/struct_selector_with_more_sugar/neva.yml +++ b/e2e/struct_selector_with_more_sugar/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/struct_selector_with_sugar/neva.yml b/e2e/struct_selector_with_sugar/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/struct_selector_with_sugar/neva.yml +++ b/e2e/struct_selector_with_sugar/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/e2e/type_expr_with_imported_type_arg/neva.yml b/e2e/type_expr_with_imported_type_arg/neva.yml index f25b3e9f..283bd401 100644 --- a/e2e/type_expr_with_imported_type_arg/neva.yml +++ b/e2e/type_expr_with_imported_type_arg/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/examples/neva.yml b/examples/neva.yml index 23a78e8a..62b66f04 100644 --- a/examples/neva.yml +++ b/examples/neva.yml @@ -1,4 +1,4 @@ -neva: 0.28.2 +neva: 0.29.0 deps: github.com/nevalang/x: path: github.com/nevalang/x diff --git a/internal/builder/tests/intergration_test.go b/internal/builder/tests/intergration_test.go index 698327e9..9728625b 100644 --- a/internal/builder/tests/intergration_test.go +++ b/internal/builder/tests/intergration_test.go @@ -19,7 +19,7 @@ func TestBuilder_WDIsModRoot(t *testing.T) { mod, ok := build.Modules[build.EntryModRef] require.True(t, ok) require.Len(t, mod.Packages, 1) - require.Equal(t, "0.28.2", mod.Manifest.LanguageVersion) // defined in yml + require.Equal(t, "0.29.0", mod.Manifest.LanguageVersion) // defined in yml pkg, ok := mod.Packages["do_nothing"] require.True(t, ok) @@ -42,7 +42,7 @@ func TestBuilder_WDIsPkg(t *testing.T) { mod, ok := build.Modules[build.EntryModRef] require.True(t, ok) require.Len(t, mod.Packages, 1) - require.Equal(t, "0.28.2", mod.Manifest.LanguageVersion) // defined in yml + require.Equal(t, "0.29.0", mod.Manifest.LanguageVersion) // defined in yml pkg, ok := mod.Packages["do_nothing"] require.True(t, ok) diff --git a/internal/builder/tests/testmod/neva.yml b/internal/builder/tests/testmod/neva.yml index f25b3e9f..283bd401 100644 --- a/internal/builder/tests/testmod/neva.yml +++ b/internal/builder/tests/testmod/neva.yml @@ -1 +1 @@ -neva: 0.28.2 \ No newline at end of file +neva: 0.29.0 \ No newline at end of file diff --git a/std/neva.yml b/std/neva.yml index 83c627dc..c5c516d1 100644 --- a/std/neva.yml +++ b/std/neva.yml @@ -1 +1 @@ -neva: 0.28.2 +neva: 0.29.0 From ec41d5a2a1f9e84a1887ca1dbc4d940ee7fd02a7 Mon Sep 17 00:00:00 2001 From: Emil Valeev Date: Sun, 15 Dec 2024 15:53:35 +0500 Subject: [PATCH 28/28] fix(examples,e2e): fix compile and runtime errors (analyzer doesn't check DI args) caused by latest changes --- e2e/99_bottles_verbose/main/main.neva | 41 +++++++++++++------ .../main/main.neva | 30 ++++++++------ .../main/main.neva | 14 ++++--- .../main/main.neva | 14 ++++--- e2e/echo_verbose/main/main.neva | 6 +-- e2e/filter_list/neva.yml | 1 - e2e/interface_anonymous/main/main.neva | 10 ++--- e2e/interface_verbose/main/main.neva | 10 ++--- e2e/interface_with_imports/main/main.neva | 14 +++---- e2e/map_list_verbose/main/main.neva | 2 +- e2e/slow_iteration_with_map/main/main.neva | 14 +++---- {e2e => examples}/filter_list/e2e_test.go | 2 - .../main => examples/filter_list}/main.neva | 6 +-- 13 files changed, 92 insertions(+), 72 deletions(-) delete mode 100644 e2e/filter_list/neva.yml rename {e2e => examples}/filter_list/e2e_test.go (95%) rename {e2e/filter_list/main => examples/filter_list}/main.neva (57%) diff --git a/e2e/99_bottles_verbose/main/main.neva b/e2e/99_bottles_verbose/main/main.neva index 9f759334..e2912cd8 100644 --- a/e2e/99_bottles_verbose/main/main.neva +++ b/e2e/99_bottles_verbose/main/main.neva @@ -4,24 +4,28 @@ import { fmt } def Main(start any) (stop any) { // we use explicit lock to implement fan-in to printNext2Lines - s Switch, PrintNext2Lines, Lock + s Switch + print_next_2_lines PrintNext2Lines + lock Lock --- :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, PrintFirstLine, PrintSecondLine + dec Dec + 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 === @@ -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, p1 fmt.Println, p2 fmt.Println, fmt.Printf, Lock, Panic + s Switch + p1 fmt.Println + p2 fmt.Println + printf fmt.Printf + lock Lock + panic Panic --- :n -> [s:data, lock:data] @@ -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 } @@ -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, p1 fmt.Println, p2 fmt.Println, p3 fmt.Println, fmt.Printf, Lock, Panic + s Switch + p1 fmt.Println + p2 fmt.Println + p3 fmt.Println + printf fmt.Printf + lock Lock + panic Panic --- :n -> [s:data, lock:data] @@ -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 } \ No newline at end of file diff --git a/e2e/add_nums_from_stdin_with_default_any/main/main.neva b/e2e/add_nums_from_stdin_with_default_any/main/main.neva index c67f0fac..e59316a9 100644 --- a/e2e/add_nums_from_stdin_with_default_any/main/main.neva +++ b/e2e/add_nums_from_stdin_with_default_any/main/main.neva @@ -1,11 +1,14 @@ import { strconv, fmt } def Main(start any) (stop any) { - Aux, fmt.Println + aux Aux + println fmt.Println + panic Panic --- - :start -> aux:sig - [aux:res, aux:err] -> println:data - println:res -> :stop + :start -> aux:sig + aux:res -> println:data + aux:err -> panic + println:res -> :stop } def Aux(sig any) (res int, err error) { @@ -13,18 +16,19 @@ def Aux(sig any) (res int, err error) { reader2 IntReader add Add --- - :sig -> reader1:sig - reader1:num -> [add:left, reader2:sig] + :sig -> reader1:sig + reader1:num -> [add:left, reader2:sig] [reader1:err, reader2:err] -> :err - reader2:num -> add:right - add:res -> :res + reader2:num -> add:right + add:res -> :res } def IntReader(sig any) (num int, err error) { - fmt.Scanln, strconv.ParseNum + scanln fmt.Scanln + parse_num strconv.ParseNum --- - :sig -> scanln:res - scanln:res -> parseNum:data - parseNum:res -> :num - parseNum:err -> :err + :sig -> scanln:sig + scanln:res -> parse_num:data + parse_num:res -> :num + parse_num:err -> :err } diff --git a/e2e/add_nums_from_stdin_with_multuple_senders/main/main.neva b/e2e/add_nums_from_stdin_with_multuple_senders/main/main.neva index 2a3f01c1..fd362d36 100644 --- a/e2e/add_nums_from_stdin_with_multuple_senders/main/main.neva +++ b/e2e/add_nums_from_stdin_with_multuple_senders/main/main.neva @@ -1,7 +1,8 @@ import { strconv, fmt } def Main(start any) (stop any) { - Aux, fmt.Println + aux Aux, + println fmt.Println --- :start -> aux:sig [aux:res, aux:err] -> println:data @@ -21,10 +22,11 @@ def Aux(sig any) (res int, err error) { } def IntReader(sig any) (num int, err error) { - fmt.Scanln, strconv.ParseNum + scanln fmt.Scanln + parse_num strconv.ParseNum --- - :sig -> scanln:res - scanln:res -> parseNum:data - parseNum:res -> :num - parseNum:err -> :err + :sig -> scanln:sig + scanln:res -> parse_num:data + parse_num:res -> :num + parse_num:err -> :err } diff --git a/e2e/add_nums_from_stdin_with_sub_components/main/main.neva b/e2e/add_nums_from_stdin_with_sub_components/main/main.neva index dbf91ccf..21f64033 100644 --- a/e2e/add_nums_from_stdin_with_sub_components/main/main.neva +++ b/e2e/add_nums_from_stdin_with_sub_components/main/main.neva @@ -1,7 +1,8 @@ import { strconv, fmt } def Main(start any) (stop any) { - Aux, fmt.Println + aux Aux + println fmt.Println --- :start -> aux:sig [aux:res, aux:err] -> println:data @@ -21,10 +22,11 @@ def Aux(sig any) (res int, err error) { } def IntReader(sig any) (num int, err error) { - fmt.Scanln, strconv.ParseNum + scanln fmt.Scanln + parse_num strconv.ParseNum --- - :sig -> scanln:res - scanln:res -> parseNum:data - parseNum:res -> :num - parseNum:err -> :err + :sig -> scanln:sig + scanln:res -> parse_num:data + parse_num:res -> :num + parse_num:err -> :err } diff --git a/e2e/echo_verbose/main/main.neva b/e2e/echo_verbose/main/main.neva index e37ebd51..ab667b56 100644 --- a/e2e/echo_verbose/main/main.neva +++ b/e2e/echo_verbose/main/main.neva @@ -1,10 +1,10 @@ import { fmt } def Main(start any) (stop any) { - fmt.Scanln - fmt.Println + scanln fmt.Scanln + println fmt.Println --- - :start -> scanln:res + :start -> scanln:sig scanln:res -> println:data println:res -> :stop } diff --git a/e2e/filter_list/neva.yml b/e2e/filter_list/neva.yml deleted file mode 100644 index f25b3e9f..00000000 --- a/e2e/filter_list/neva.yml +++ /dev/null @@ -1 +0,0 @@ -neva: 0.28.2 \ No newline at end of file diff --git a/e2e/interface_anonymous/main/main.neva b/e2e/interface_anonymous/main/main.neva index a2040184..2d670d69 100644 --- a/e2e/interface_anonymous/main/main.neva +++ b/e2e/interface_anonymous/main/main.neva @@ -1,17 +1,17 @@ import { fmt } def Main(start any) (stop any) { - second_flow Secondflow {fmt.Println} + second_flow Secondflow{fmt.Println} --- :start -> second_flow:data second_flow:res -> :stop } def Secondflow (data any) (res any) { - iPrinter IPrinter + printer IPrinter --- - :data -> iPrinter:res - iPrinter:sig -> :res + :data -> printer:data + printer:res -> :res } -interface IPrinter(T) (T) +interface IPrinter(data T) (res T) diff --git a/e2e/interface_verbose/main/main.neva b/e2e/interface_verbose/main/main.neva index 1cd1cfaf..4fa45f0f 100644 --- a/e2e/interface_verbose/main/main.neva +++ b/e2e/interface_verbose/main/main.neva @@ -2,7 +2,7 @@ import { fmt } def Main(start any) (stop any) { second_flow Secondflow { - dep_node fmt.Println + printer fmt.Println } --- :start -> second_flow:data @@ -10,10 +10,10 @@ def Main(start any) (stop any) { } def Secondflow (data any) (res any) { - dep_node IPrinter + printer IPrinter --- - :data -> dep_node:res - dep_node:sig -> :res + :data -> printer:data + printer:res -> :res } -interface IPrinter(T) (T) +interface IPrinter(data T) (res T) diff --git a/e2e/interface_with_imports/main/main.neva b/e2e/interface_with_imports/main/main.neva index 5fc5edd9..189027fa 100644 --- a/e2e/interface_with_imports/main/main.neva +++ b/e2e/interface_with_imports/main/main.neva @@ -1,17 +1,17 @@ import { github.com/nevalang/x:main } def Main(start any) (stop any) { - second_flow Secondflow{main.Println} + sub_component SubComponent{main.Println} --- - :start -> second_flow:data - second_flow:res -> :stop + :start -> sub_component:data + sub_component:res -> :stop } -def Secondflow (data any) (res any) { +def SubComponent(data any) (res any) { printer IPrinter --- - :data -> printer:res - printer:sig -> :res + :data -> printer:data + printer:res -> :res } -interface IPrinter(T) (T) +interface IPrinter(data T) (res T) diff --git a/e2e/map_list_verbose/main/main.neva b/e2e/map_list_verbose/main/main.neva index 8229ec77..5722b17c 100644 --- a/e2e/map_list_verbose/main/main.neva +++ b/e2e/map_list_verbose/main/main.neva @@ -7,7 +7,7 @@ const lst list = [50, 30, 20, 100] def Main(start any) (stop any) { map_decr Map{Dec} s2l StreamToList - println fmt.Println + println fmt.Println> l2s ListToStream --- :start -> $lst -> l2s -> map_decr -> s2l -> println -> :stop diff --git a/e2e/slow_iteration_with_map/main/main.neva b/e2e/slow_iteration_with_map/main/main.neva index ff1de75e..1ce061ed 100644 --- a/e2e/slow_iteration_with_map/main/main.neva +++ b/e2e/slow_iteration_with_map/main/main.neva @@ -7,17 +7,17 @@ import { time, fmt } const lst list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] def Main(start any) (stop any) { - ListToStream - Map{Slow} - List - fmt.Println> + l2s ListToStream + map Map{Slow} + s2l StreamToList + println fmt.Println> --- - :start -> $lst -> listToStream -> map -> list -> println -> :stop + :start -> $lst -> l2s -> map -> s2l -> println -> :stop } def Slow(data int) (res int) { - time.Delay - Dec + delay time.Delay + dec Dec --- :data -> delay:data $time.second -> delay:dur diff --git a/e2e/filter_list/e2e_test.go b/examples/filter_list/e2e_test.go similarity index 95% rename from e2e/filter_list/e2e_test.go rename to examples/filter_list/e2e_test.go index 80ed4992..b18adc9b 100644 --- a/e2e/filter_list/e2e_test.go +++ b/examples/filter_list/e2e_test.go @@ -11,8 +11,6 @@ import ( ) func Test(t *testing.T) { - t.Skip("skipping for now") // TODO - err := os.Chdir("..") require.NoError(t, err) diff --git a/e2e/filter_list/main/main.neva b/examples/filter_list/main.neva similarity index 57% rename from e2e/filter_list/main/main.neva rename to examples/filter_list/main.neva index dcbf0a5b..3495b4f7 100644 --- a/e2e/filter_list/main/main.neva +++ b/examples/filter_list/main.neva @@ -1,14 +1,14 @@ import { fmt } -const lst list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +const numbers list = [2, 4, 6, 8, 10] def Main(start any) (stop any) { - l2s ListToStream + list_to_stream1 ListToStream filter_even Filter{predicate Even} for_print For{fmt.Println} wait Wait --- - :start -> $lst -> l2s -> filter_even -> for_print -> wait -> :stop + :start -> $numbers -> list_to_stream1-> filter_even -> for_print -> wait -> :stop } def Even(data int) (res bool) {