diff --git a/cmd/vm/main.go b/cmd/vm/main.go index e42c1091..1a59adc0 100644 --- a/cmd/vm/main.go +++ b/cmd/vm/main.go @@ -4,7 +4,7 @@ import ( "context" "os" - "github.com/nevalang/neva/internal/pkg/disk" + "github.com/nevalang/neva/internal/vm/repo/disk" "github.com/nevalang/neva/internal/runtime" "github.com/nevalang/neva/internal/runtime/funcs" "github.com/nevalang/neva/internal/vm" diff --git a/docs/spec/faq.md b/docs/faq.md similarity index 100% rename from docs/spec/faq.md rename to docs/faq.md diff --git a/docs/ideas.md b/docs/ideas.md deleted file mode 100644 index f6611ec0..00000000 --- a/docs/ideas.md +++ /dev/null @@ -1,331 +0,0 @@ - -``` -all flags are optional - -neva: - run # run interpreter - - i | --interactive # interactive mode - build # run compiler - -t | --target = executable (default) | ir | go | js | ts | wasm - -neva run -neva run -i | --interactive -``` - -## GPT-like model for docs search - -# Naming/Refactoring - -- Rename trigers to lockers? - -# Examples why FBP better - -1. implicit state mutations are impossible -2. race conditions are impossible due to messages immutability (and lack of shared state?) -3. deadlocks are impossible because of no flow control (it's runtime who run goroutines and not end-user) -4. concurrent code isn't harder to maintain (real world is asynchronous) -5. type system: nominal typing and freedom from unnecessary type casts and mappings -6. type system: no nil pointer dereference -7. things goes exactly where we want (e.g. impossible to handle invalid response because of unhandled error. it's possible not to handle error, but that only means nothing will happen) -8. performance - concurrency by default everywhere (things to parallel are everywhere) -9. ready for future with lots of cores -10. always be as fast as go due to usage of go source code as a perfect and very high-level compile-target -11. perfect for visualizations and perfectly shows execution flow - data-charts as programs done right - - -# Defer - -We have `defer` in Go. Do we need/can have this in FBP? - -# Filter - -In classical FBP filter works differently. -Is uses sort of optional IP to specify field in the IP with bool. - -# Sequencizer component - -From fbp book: - -> Во всех существующих системах FBP есть очень полезный компонент, который просто принимает и отдаёт все IP из своего первого входного порта, за которыми следуют все IP из его второго входного порта, и так далее, пока все пакеты в слотах не закончатся. В DFDM это называлось Sequencizer (некоторые мои друзья любят играть с английским языком). Этот компонент часто используется для принудительного создания последовательности данных, которые генерируются случайным образом из различных источников. Одним из примеров могут быть контрольные итоги, генерируемые различными процессами, которые затем вы хотите распечатать в фиксированном порядке в отчете. Вы знаете последовательность, в которой хотите, чтобы они отображались, но не знаете время, в которое они будут созданы. - -# General Purpose Router? - -```yml -io: - arg: [x, y, z] - in: - a[]: x -``` - -# SubStreams to array outports - -Introduce component that allows to turn substream values into array-outport firings. - -## Problem - -Slots are compiled-timed - -# Graphical notation for network - -- Triangles for in-out -- Squares for constants/memory -- Circles for components (ops/mods) - -# Context as a program primitive? - -Introduce outport to root module? - -# The flatter the faster - -Optimize runtime structures including proto? - -# Website in a rpg-manner - -Tutorials like chapters in game -They require knowledge of specific topics -You go into them in a right order - -# Minimize flow - -Instead of require user to use `Filter` make `More` (and stuff like that) more friendly. -Instead of having `More.Out.Result` (true or false) you can have `Out.True` and `Out.False` which passes -given element next. - -But how to solve task "for every user that is older than 30 years send a message `yo`"? - -# Data editor - -Data editor is a mind-map-like GUI -that allowes create graph -where one can leads to another - -a way to visualize message interface creation - -# BLACK ADAPTERS MAGIC!!! - -Модуль, который динамически создаёт другие модули. -Кейс - динамическое создание адаптера между компонентом, который принимает список -и компонентом, который имеет аррай-портс интерфейс. - -При старте такой модуль создаёт аррай портс с кол-ом ячеек соотв. длине списка. -При получении значения он пишет в этот порт. - -## Motivation - -Test is simply a program that uses (e.g. `std/testing`) test utils - -## Mock API (go:generate-ish?) - -??? - -``` -prog1.yml -prog2.yml -common/ - mod1.yml -prog1/ - mod2.yml -prog2/ - mod3.yml - -neva run prog1.yml -``` - -# Debugger - -## Undo/Redo - -Instead of keeping log of all sends/receives, keep only previous values. - -## Editing of messages values - -## Live changing of networks - -- Обмен байткодом между рантаймами -- DEBUGGER (Обёртка над компилятором и рантаймом, в рантайме, вероятно, мидлварь) -- FBP SHELL -- mocker? -- type system (типы должны быть максимально просты и совместимы с `gRPC`, `graphQL` и `json schema`) -- Close all the ports when there are no senders to receive a message from. - -# REPL - -... - -# WEB (old) - -```tsx -import * as React from "react"; -import * as rf from "reaflow"; -import { hasLink, NodeData, removeNode, getEdgesByNode } from "reaflow"; - -export function App() { - const [selections, setSelections] = React.useState([]); - - const [nodes, setNodes] = React.useState([ - { - id: "in", - text: "in", - ports: [ - { - id: "x", - height: 10, - width: 10, - side: "SOUTH", - }, - ], - }, - { - id: "multi", - text: "multi", - ports: [ - { - id: "nums[0]", - height: 10, - width: 10, - side: "NORTH", - }, - { - id: "nums[1]", - height: 10, - width: 10, - side: "NORTH", - }, - { - id: "mul", - height: 10, - width: 10, - side: "SOUTH", - }, - ], - }, - { - id: "out", - text: "out", - ports: [ - { - id: "y", - height: 10, - width: 10, - side: "NORTH", - }, - ], - }, - ]); - - const [edges, setEdges] = React.useState([ - { - id: "in.x-multi.nums[0]", - from: "in", - to: "multi", - fromPort: "x", - toPort: "nums[0]", - }, - { - id: "in.x-multi.nums[1]", - from: "in", - to: "multi", - fromPort: "x", - toPort: "nums[1]", - }, - { - id: "multi.mul-out.y", - from: "multi", - to: "out", - fromPort: "mul", - toPort: "y", - }, - ]); - - const [draggingPort, setDraggingPort] = React.useState(""); - - return ( -
- setSelections([])} - onNodeLinkCheck={(_, from, to) => !hasLink(edges, from, to)} - onNodeLink={(_, fromNode, toNode) => { - // TODO link ports, not nodes! - setEdges([ - ...edges, - { - id: `${fromNode.id}-${toNode.id}`, - from: fromNode.id, - to: toNode.id, - }, - ]); - }} - edge={ - setSelections([edge.id])} - // onEnter={console.log} - // onLeave={console.log} - onRemove={(_, e) => { - setEdges(edges.filter((edge) => edge.id !== e.id)); - }} - onAdd={console.log} - /> - } - node={ - console.log(port)} - // onLeave={(_, port) => console.log(port)} - onClick={(_, node) => setSelections([node.id])} - onRemove={(_event, node) => { - const results = removeNode(nodes, edges, [node.id]); - setNodes(results.nodes); - setEdges(results.edges); - }} - port={ - setSelections([port.id])} - // onEnter={(_, port) => console.log(port)} - // onLeave={(_, port) => console.log(port)} - onDragStart={(...a) => console.log("start", ...a)} - onDragEnd={(...a) => console.log("end", ...a)} - style={{ fill: "black", stroke: "white", strokeWidth: "1px" }} - rx={10} - ry={10} - /> - } - /> - } - /> -
- ); -} -``` diff --git a/docs/intro.md b/docs/intro.md deleted file mode 100644 index 3718a47e..00000000 --- a/docs/intro.md +++ /dev/null @@ -1,41 +0,0 @@ -# Introduction - -_Package_ is a set of _entities_ separated by files all located in the same directory. Name of the directory is the name of the package. - -There are special rules dictating how package should be separated into files, enforced by _linter_, but it only serve maintanability purpose. It doesn't matter for _compiler_ whether package is one big file or many small ones. We well discuss these rules later. - -There are 4 types of _entity_ package can contain: _type_, _interface_, _constant_ and _component_, each having correspondinging keyword: `type`, `io`, `const` and `comp`. - -Each entity can be either _private_ or _public_. Every entity is private by default and could be made public by using `pub` keyword. Private entity means it cannot be used outside of the package while public means it could be _imported_ by using `use` keyword. - -Set of packages located in the same directory form a _project_. There's usually one project per git repository, but that's not necessary. Every project must have `proj.yml` in root directory. This file describe wanted compiler version and dependencies. - -Every project must contain at least one _executable_ package. Executable package is a package that - -# Maintainability guide - -## Naming - -- Components named in UpperCamelCase with "er" ending like `Printer`. Name must express that component is _doing_ something -- Types are also named in UpperCamelCase, not necessarily with "er" ending. E.g. `MyInt` -- Interfaces are named just like components but with `I` prefix. E.g. `IReader` -- Constants are named in `UPPER_SNAKE_CASE`. E.g. `PI` or `DB_TIMEOUT` -- Nodes are named just like components but in lowerCamelCase. E.g. `printer = Printer()`. Similar to how class instances usually named in OOP languages -- Packages are named in lower_snake_case. E.g. `json` or `build_info` -- Port are named shortly, following _port naming convention_, if possible: - - `v` for _value_ - - `sig` for _signal_ - - `err` for _error_ - - First letter of the type otherwise: E.g. port with `User` type must me named `u` - - Port that accepts array or vector must be named like regular port but with doubled letter or with "s" on the end. E.g. `vv`, `uu` or `errs` - - If following this convention makes code less readable then an exception could be made. Common sense is still there. There could be something wrong with the design though. - - -Before we discussed that there are _special rules_ about how entities are located in the package. Again, these rules enforced by linter and not compiler, which means _program will work just fine without these_. But one of the main goals of this language is to make programs as maintainable as possible. - -- If there's more than 1 entity of the same type in the file, then they must be grouped. -- Order of entities in the file must be: `use, type, io, const, comp` -- Each file must contain one component and entities that are used by that component. Those entities could also be `pub` though. One file should not refer to entities defined in other files in the same package. -- One exception to previous rule is `*.shared.neva` files. There could be one `shared.neva` file or many of them e.g. `interfaces.shared.neva` and `const.shared.neva` -- Entities defined in this _shared_ files could be referenced from any other file in the same package including other shared files. But there must be (it won't compile otherwise) no dependency cycle -- diff --git a/docs/moved_from_readme.md b/docs/moved_from_readme.md deleted file mode 100644 index aff3ac4b..00000000 --- a/docs/moved_from_readme.md +++ /dev/null @@ -1,75 +0,0 @@ -## Safety - -**If it runs - it works**. - -Thanks to dataflow paradigm, where programmer doesn't interact with low-level promitives like variables, pointers or coroutines, and static type-system. If compiler accepted the program and the program started successfully, then there's a guarantee that there will be no exceptional situations including: - -- [Race conditions](https://en.wikipedia.org/wiki/Race_condition) -- [Deadlocks](https://en.wikipedia.org/wiki/Deadlock) -- [Type errors](https://en.wikipedia.org/wiki/Type_system#Type_errors) -- [Null pointer](https://en.wikipedia.org/wiki/Null_pointer) aka [The Billion Dollar Mistake](https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/) -- [Uninitialized variables](https://en.wikipedia.org/wiki/Uninitialized_variable) -- [Off-by-one](https://en.wikipedia.org/wiki/Off-by-one_error) and [indexing errors](https://en.wikipedia.org/wiki/Bounds_checking#Index_checking) in general -- [Stack overflow](https://en.wikipedia.org/wiki/Stack_overflow) -- [And](https://en.wikipedia.org/wiki/Dangling_pointer) [many](https://en.wikipedia.org/wiki/Buffer_overflow) [many](https://en.wikipedia.org/wiki/Segmentation_fault) [more](https://en.wikipedia.org/wiki/Stale_pointer_bug) - -Any runtime error is threated as a compiler bug. - -## Performance - -### Complete asynchrony - -Data gets processed as soon as it arrives. Concider this pseudocode: - -``` -sumRoots( - getRootA(), - getRootB(), -) -``` - -Both `getRootA()` and `getRootB()` return numbers, `sumRoots` find square roots for those numbers and returns their sum. In conventional programming we have to wait for `getRootA`, then for `getRootB` and then for `sumRoots`. In FBP all three `sumRoots`, `getRootA` and `getRootB` runs concurrently. No matter which finishes first, as soon as first number arrive, `sumRoots` start executing. At the time second number arrive, the first square root could already be calculated. Imagine the whole program work this way. - -### Implicit parallelism - -FBP processes don't share memory and thus can run in parallel. Everything that can happen at the same time - will. Programmer doesn't intereact with threads, mutexes, coroutines or channels. Not only it eliminate concurrency-related bugs but also forces the program to utilize all CPU cores. - -### As fast as Go - -[Go](https://go.dev) is used as a low-level IR due to several reasons. - -1. Perfect match. FBP's processes and ports maps 1-1 to Go's goroutines and channels (because [CSP](https://en.wikipedia.org/wiki/Communicating_sequential_processes), the formal model that Go based on, is a form of Dataflow programming). This makes Go perfect choice for low-level IR for FBP language. -2. State of the art [standard library](https://pkg.go.dev/std), coroutine scheduler, garbage collector and crossplatform machine code generation backed by huge community. Nevalang will become faster and safer by simply updating the underlying Go compiler. -3. One of the fastest compilers in the world. Compilation speed is [design](https://www.youtube.com/watch?v=rKnDgT73v8s#t=8m53) goal. - -From some point Nevalang could be viewed as a Go code generator. - -## Productivity - -### Implicit parallelism - -Implicit parallelism makes concurrent programming as simple as a regular one. Programmers used to think that concurrent programs are harder to reason about and thus test and maintain but that's not true in FBP. - -### Static analysis - -Thanks to graph-like nature of FBP programs and static types compiler can catch most of the possible errors. And everything compiler can't catch is checked at program's startup. So there's just the actual program's logic that programmer have to think about. Many situations like "error was handled like a valid result" or "class was initialized with null dependencies" are simply impossible. - -### Interpreter mode - -Iterate fast by using interpreter instead of compiler for development and see changes in realtime. Nevalang architecture allows to use the exact same code analyzer and runtime without the need to generate executable. So you can develop like it's Node.js with TS out of the box. Then compile it to fast executable when it's ready for production. - -### Multiplayer mode - -Nevalang comes with development server that allowes several developers at the same time to connect and modify the same program. Everyone can see changes in realtime. - -### Observability out of the box - -Message interceptor is built into the runtime and every message has trace so it's extremely easy to keep track of how data is moving across the program. Same goes for errors - you can see where error arose and what way did it went. You can debug probram by setting breakpoints on the graph connections and intercept messages. You can even substitute them on the fly to see what will happen. - -### Visual programming - -Last but not least. FBP is a perfect paradigm for visual programming because FBP programs are literally computational graphs - processes connected to each other through input and output ports. Making visual representation of a FBP program is simply rendering it's structure. - -There's a big problem with visual representations of a software written in conventional langauge - they're dead. There's no connection with the real code. But FBP schema _is_ the code. So the most productive way to work with Nevalang must be by working with visual schemas. Move blocks around and wire stuff up. - -It doesn't mean it's the only way to program in Nevaland. Think of visual editor as a source code generator. Generated code must be completely human-readable because we still need to review it. There probably will be usecases for hand-written code (e.g. REPL). Or maybe you just an old fashioned hacker. diff --git a/docs/notes.md b/docs/notes.md deleted file mode 100644 index 8169cd7b..00000000 --- a/docs/notes.md +++ /dev/null @@ -1,51 +0,0 @@ -# Memory conclusions - -- pointer: 8 bytes -- interface: 16 bytes -- slice: 24 bytes -- string: 16 bytes -- struct: sum of fields - -# Chan info - -- Safe to receive from closed chan (default value) -- Unsafe to send to closed chan (panic) - -# Ports buf sizes - -компилятор пытается сгенерировать программу таким образом -чтобы у каналов были буфферы, релевантные их использованию (продумать) -чтобы рантайму не пришлось подключать механику очередей - -однако рантайм способен обслуживать каналы таким образом -чтобы они никогда не блокировались -используя ручные очереди - -## Compiler - -выходные порты никогда не имеют буфера -т.к. рантайм вычитывает их в неблокирующем режиме -иными словами, рантайм всегда сможет вычитать сообщение из выходного порта так быстро -как это только возможно - -для входных портов размер буфера равен количеству пишущих в них выходных портов -это предположение, основанное на том, что чем у получателя больше отправителей -тем быстрее может наполняться его буфер - -конечно, реальность сложнее -один быстрый отправитель может заполнить буфер быстрее чем несколько медленных -однако, лучше иметь буфер, чем не иметь его -а его размер должен быть как-то обоснован - -рантайм, однако, устроен таким образом -что при переполнении буфера подключаются "ручные очереди" -которыми он управляет сам -благодаря чему порты, которые способны принять сообщение, будут тут же принимать его -не будучи никак заблокированы операциями, с ними не связанными - -## Runtime - -от отправителя пришло сообщение -это сообщение надо передать всем -надо сделать это так, чтобы передача сообщения одному получателю не была заблокирована другой предачей -для этого рантайм использует очереди diff --git a/docs/spec/README.md b/docs/spec/README.md deleted file mode 100644 index 1f33ae97..00000000 --- a/docs/spec/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# How to read this - -- If you see unknown word lookup [abbreviations](./abbrs.md) and [glossary](./glossary.md). - diff --git a/docs/spec/abbrs.md b/docs/spec/abbrs.md deleted file mode 100644 index f8005bb1..00000000 --- a/docs/spec/abbrs.md +++ /dev/null @@ -1,29 +0,0 @@ -# Abbreviations - -- expr - expression -- lit - (type) literal expression -- inst - (type) instantiation expression -- compat - (type) compatibility -- enum - enumeration -- union - untagged union (sum-type) -- arr - array (static array) -- vec - vector (slice, dynamic array) -- rec - record (structure, product type) -- int - integer digit -- i8, i16, i32, i64 - N bit integer -- float - floating point digit -- f32, f64 - N bit float -- num - number/numeric -- bool - boolean -- str - string -- ref - reference -- arg - argument -- param - parameter -- params - parameters -- el - element -- els - elements -- k - key -- v - value -- t - type -- ssi - SubStreamItem +```tsx +import * as React from "react"; +import * as rf from "reaflow"; +import { hasLink, NodeData, removeNode, getEdgesByNode } from "reaflow"; -- find main pkg and main component to use it as a root node -- get its io and create nodeCtx for root node with path "" - -- for every connection generate IR connection add IR connection with the path from nodeCtx ---DONE--- - - while doing so, count incoming connections for every node inport in the network (to create new nodeCtx) and outgoing connections for every outport (to create void connections later when iterating nodes) - - don't forget about giver and void connections! (void connections could be added later) -- iterate over nodes - - if its refs to native then add IR func ref - - if it does have static ports then create IR giver for every inport and corresponding message and add giver connection +export function App() { + const [selections, setSelections] = React.useState([]); -generate(nodeCtx) + const [nodes, setNodes] = React.useState([ + { + id: "in", + text: "in", + ports: [ + { + id: "x", + height: 10, + width: 10, + side: "SOUTH", + }, + ], + }, + { + id: "multi", + text: "multi", + ports: [ + { + id: "nums[0]", + height: 10, + width: 10, + side: "NORTH", + }, + { + id: "nums[1]", + height: 10, + width: 10, + side: "NORTH", + }, + { + id: "mul", + height: 10, + width: 10, + side: "SOUTH", + }, + ], + }, + { + id: "out", + text: "out", + ports: [ + { + id: "y", + height: 10, + width: 10, + side: "NORTH", + }, + ], + }, + ]); -# Src to IR + const [edges, setEdges] = React.useState([ + { + id: "in.x-multi.nums[0]", + from: "in", + to: "multi", + fromPort: "x", + toPort: "nums[0]", + }, + { + id: "in.x-multi.nums[1]", + from: "in", + to: "multi", + fromPort: "x", + toPort: "nums[1]", + }, + { + id: "multi.mul-out.y", + from: "multi", + to: "out", + fromPort: "mul", + toPort: "y", + }, + ]); -- generating IR should happen in a tree manner from root to leafs -- every analyzed node on that path means adding ports to program -- every node means component. if it's interface then find out how it's instantiated -- every component means adding new connections (network) or operator (effect) + const [draggingPort, setDraggingPort] = React.useState(""); -# IR to Go - -- Simply include imports (for runtime, operators, code) or exactly copy/generate that code? -- Do we need `core` as a separate package? - -# Issues - -- deadlock detection? -- sure races are impossible? -- do we need transactions? -- ensure that any backwards compatible package could be used everywhere we assume lower forward compatible package (make semver incompatibility impossible) -- Blockchain package and docs management? + return ( +
+ setSelections([])} + onNodeLinkCheck={(_, from, to) => !hasLink(edges, from, to)} + onNodeLink={(_, fromNode, toNode) => { + // TODO link ports, not nodes! + setEdges([ + ...edges, + { + id: `${fromNode.id}-${toNode.id}`, + from: fromNode.id, + to: toNode.id, + }, + ]); + }} + edge={ + setSelections([edge.id])} + // onEnter={console.log} + // onLeave={console.log} + onRemove={(_, e) => { + setEdges(edges.filter((edge) => edge.id !== e.id)); + }} + onAdd={console.log} + /> + } + node={ + console.log(port)} + // onLeave={(_, port) => console.log(port)} + onClick={(_, node) => setSelections([node.id])} + onRemove={(_event, node) => { + const results = removeNode(nodes, edges, [node.id]); + setNodes(results.nodes); + setEdges(results.edges); + }} + port={ + setSelections([port.id])} + // onEnter={(_, port) => console.log(port)} + // onLeave={(_, port) => console.log(port)} + onDragStart={(...a) => console.log("start", ...a)} + onDragEnd={(...a) => console.log("end", ...a)} + style={{ fill: "black", stroke: "white", strokeWidth: "1px" }} + rx={10} + ry={10} + /> + } + /> + } + /> +
+ ); +} +``` diff --git a/internal/compiler/compiler.go b/internal/compiler/compiler.go index 5e18c1e8..f5a65d98 100644 --- a/internal/compiler/compiler.go +++ b/internal/compiler/compiler.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/nevalang/neva/internal/src" + "github.com/nevalang/neva/internal/compiler/src" "github.com/nevalang/neva/pkg/ir" ) @@ -59,8 +59,12 @@ func (c Compiler) Compile(ctx context.Context, srcPath, dstPath string) (*ir.Pro return nil, fmt.Errorf("generate: %w", err) } + if dstPath == "" { + return irProg, nil + } + if err := c.repo.Save(ctx, dstPath, irProg); err != nil { - return nil, err + return nil, fmt.Errorf("repo save: %w", err) } return irProg, nil diff --git a/internal/compiler/irgen/irgen.go b/internal/compiler/irgen/irgen.go index 979d6e3c..ae839e30 100644 --- a/internal/compiler/irgen/irgen.go +++ b/internal/compiler/irgen/irgen.go @@ -7,7 +7,7 @@ import ( "fmt" "strings" - "github.com/nevalang/neva/internal/src" + "github.com/nevalang/neva/internal/compiler/src" "github.com/nevalang/neva/pkg/ir" "golang.org/x/exp/maps" ) diff --git a/internal/compiler/parser/listener.go b/internal/compiler/parser/listener.go index a65e7eda..bbf903be 100644 --- a/internal/compiler/parser/listener.go +++ b/internal/compiler/parser/listener.go @@ -5,7 +5,7 @@ import ( "strings" generated "github.com/nevalang/neva/internal/compiler/parser/generated" - "github.com/nevalang/neva/internal/src" + "github.com/nevalang/neva/internal/compiler/src" "github.com/nevalang/neva/pkg/ts" ) diff --git a/internal/compiler/parser/listener_helpers.go b/internal/compiler/parser/listener_helpers.go index 4fb0fe0a..57a7b0e9 100644 --- a/internal/compiler/parser/listener_helpers.go +++ b/internal/compiler/parser/listener_helpers.go @@ -2,7 +2,7 @@ package parser import ( generated "github.com/nevalang/neva/internal/compiler/parser/generated" - "github.com/nevalang/neva/internal/src" + "github.com/nevalang/neva/internal/compiler/src" "github.com/nevalang/neva/pkg/ts" ) diff --git a/internal/compiler/parser/parser.go b/internal/compiler/parser/parser.go index 74b00b9d..224f99d6 100644 --- a/internal/compiler/parser/parser.go +++ b/internal/compiler/parser/parser.go @@ -8,7 +8,7 @@ import ( "golang.org/x/sync/errgroup" generated "github.com/nevalang/neva/internal/compiler/parser/generated" - "github.com/nevalang/neva/internal/src" + "github.com/nevalang/neva/internal/compiler/src" ) type treeShapeListener struct { diff --git a/internal/src/src.go b/internal/compiler/src/src.go similarity index 100% rename from internal/src/src.go rename to internal/compiler/src/src.go diff --git a/internal/compiler/std/std.go b/internal/compiler/std/std.go index edd8dc26..75f44f43 100644 --- a/internal/compiler/std/std.go +++ b/internal/compiler/std/std.go @@ -2,7 +2,7 @@ package std import ( - "github.com/nevalang/neva/internal/src" + "github.com/nevalang/neva/internal/compiler/src" "github.com/nevalang/neva/pkg/ts" ) diff --git a/internal/interpreter/compiler_repo.go b/internal/interpreter/compiler_repo.go deleted file mode 100644 index 5585e000..00000000 --- a/internal/interpreter/compiler_repo.go +++ /dev/null @@ -1,24 +0,0 @@ -package interpreter - -import ( - "context" - - "github.com/nevalang/neva/internal/pkg/disk" - "github.com/nevalang/neva/pkg/ir" -) - -// CompilerRepo is compiler.Repo implementation that -// allows compiler to read source code from disc but disallows it to write IR back. -type CompilerRepo struct { - disk.Repository -} - -func (c CompilerRepo) Save(ctx context.Context, path string, prog *ir.Program) error { - return nil -} - -func NewCompilerRepo(repo disk.Repository) CompilerRepo { - return CompilerRepo{ - Repository: repo, - } -} diff --git a/internal/pkg/disk/disk.go b/internal/vm/repo/disk/disk.go similarity index 63% rename from internal/pkg/disk/disk.go rename to internal/vm/repo/disk/disk.go index 7bd94836..25750b7a 100644 --- a/internal/pkg/disk/disk.go +++ b/internal/vm/repo/disk/disk.go @@ -3,7 +3,6 @@ package disk import ( "context" "fmt" - "io/fs" "os" ) @@ -17,14 +16,6 @@ func (r Repository) ByPath(ctx context.Context, path string) ([]byte, error) { return file, nil } -func (r Repository) Save(path string, bb []byte) error { - err := os.WriteFile(path, bb, fs.ModePerm) - if err != nil { - return fmt.Errorf("write file: %w", err) - } - return nil -} - func MustNew() Repository { return Repository{} }