/r/ProgrammingLanguages
This subreddit is dedicated to the theory, design and implementation of programming languages.
This subreddit is dedicated to the theory, design and implementation of programming languages.
Be nice to each other. Flame wars and rants are not welcomed. Please also put some effort into your post, this isn't Quora.
This subreddit is not the right place to ask questions such as "What language should I use for X", "what language should I learn", "what's your favourite language" and similar questions. Such questions should be posted in /r/AskProgramming or /r/LearnProgramming. It's also not the place for questions one can trivially answer by spending a few minutes using a search engine, such as questions like "What is a monad?".
/r/ProgrammingLanguages
With some recent improvements the way Pipefish does Golang interop has gone from a shameful hack with limited features to a little technical gem that does everything.
How it works from the user end is nice and simple. You can write the signature of a function in Pipefish, and the body in Go, joined by the golang
keyword as a Pipefish-to-Go converter:
fib(n int) : golang {
a := 0
b := 1
for i := 0; i <= n; i++ {
a, b = b, a + b
}
return a
}
This gives access to the extra speed of Go, and makes it trivial or indeed automatable to turn Pipefish libraries into standard libraries.
To make this nice for everyone we have interop on the type level: we can pass around all the basic types; all the container types (lists, maps, sets, pairs), and lambdas. (The lambdas aren't just to show off, the Go people are into libraries with functions that take functions as arguments. So passing them is important. Returning them was to show off, I can't think why anyone would want to.)
And then the user-defined types in the Pipefish code are known to any Go function that needs to know about them:
newtype
Dragon = struct(name string, color Color, temperature Temperature)
Color = enum RED, GREEN, GOLD, BLACK
Temperature = clone int
def
// Returns the color of the hottest dragon.
dragonFight(x, y Dragon) -> Color : golang {
if x.Temperature >= y.Temperature {
return x.Color
}
return y.Color
}
All this "just works" from the POV of the user.
How it works on the inside
This time I thought I'd give the technical details because the other Gophers would want to see. I think the only thing that could be significantly better than this is if using the plugin
package at all is a local optimum and there's an overall better architecture in which case let me know. (Please, urgently.)
Go has a plugin
package. The way it works is in principle very simple. You tell the Go compiler to compile your code into a .so
file rather than an ordinary executable. You can then point the plugin
package at the .so
file and slurp out any public function (by name) into a Value type which you can then cast to a function type:
plugin, _ := plugin.Open("plugin_name.so")
fooValue, _ := p.Lookup("Foo")
myFooFunction := fooValue.(func(x troz) zort)
myFooFunction
now does the same as Foo
, and as I understand it, does so without overhead, it just is the original function.
(In practice this is rickety as heck and also Google hasn't bothered to spend any of their vast cash on making this supposedly "standard" library work for the Windows version of Go. The discussion on why not includes the comment that it is "mostly a tech demo that for some unholy reason got released as a stable feature of the language". I can't do anything about any of this except maybe send roadkill through the mail to all concerned. However, when using the plugin package I have learned to turn around three times and spit before invoking the juju and it's working out for me.)
Sooo ... all we have to do is take the embedded Go out of the Pipefish script, compile it, and it should run, and then we slurp the Go function out of the plugin, tell the compiler to wrap the Pipefish signatures around it, and Bob's your uncle, right?
Well, not quite. Because for one thing, all the embedded Go is in the bodies of the functions. The signatures are in Pipefish:
// Returns the color of the hottest dragon.
dragonFight(x, y Dragon) -> Color : golang {
if x.Temperature >= y.Temperature {
return x.Color
}
return y.Color
}
So we need to translate the signature into Go. No problem:
func DragonFight(x Dragon, y Dragon) Color {
if x.Temperature >= y.Temperature {
return x.Color
}
return y.Color
}
And of course we're going to have to generate some type declarations. Also easy:
type Temperature int
type Dragon struct {
Name string
Color Color
Temperature Temperature
}
type Color int
const (
RED Color = iota
GREEN
GOLD
BLACK
)
Now our generated code knows about the types. But our runtime doesn't. So what we do is generate code defining a couple of variables:
var PIPEFISH_FUNCTION_CONVERTER = map[string](func(t uint32, v any) any){
"Dragon": func(t uint32, v any) any {return Dragon{v.([]any)[0].(string), v.([]any)[1].(Color), v.([]any)[2].(Temperature)}},
"Color": func(t uint32, v any) any {return Color(v.(int))},
"Temperature": func(t uint32, v any) any {return Temperature(v.(int))},
}
var PIPEFISH_VALUE_CONVERTER = map[string]any{
"Color": (*Color)(nil),
"Temperature": (*Temperature)(nil),
"Dragon": (*Dragon)(nil),
}
Then the Pipefish compiler slurps these in along with the functions, turns them into (a) a map from Pipefish type numbers to the functions (b) a map from Go types to Pipefish type numbers, and stores this data in the VM. This provides it with all the information it needs to translate types.
.so
file and does housekeeping..go
source file.Can I glue all the languages?
Rust, for example, is a nice language. Can I glue it into Pipefish in the same way?
In principle, yes. All I have to do is make the compiler recognize things that say rust {
like it now does things that say golang {
, and write a thing to generate Rust code and compile it, and then another thing to generate a Go plugin that knows how to do FFI with the compiled Rust. Simple. Ish. Of course, there are lots of languages, many of which I don't know (Rust, for example) and so working my way through them all would not be a good use of my time.
However. Suppose I make a languages
folder in the Pipefish app that people can drop .go
files into. For example rust.go.
These files would be converted into .so
files by the Pipefish compiler (people can't just supply ready-compiled .so
files themselves because of version compatibility nonsense) Each such file would contain a standardized set of functions saying how to generate the source code for the target language, how to make object code from the source code, and how to write a .go
file that compiles into a .so
file that can do FFI with the object code in the target language.
So then anyone who wanted to could write a plugin to add another language you could glue into your Pipefish code.
I don't see why it wouldn't work. Perhaps I'm missing something but it seems like it would.
In Miranda, comparison operators can be chained, e.g.
if 0 <= x < 10
desugars in the parser to
if 0 <= x & x < 10
This extends to any length for any comparison operator producing a Bool:
a == b == c < d
is
a == b & b == c & c < d
I like this, as it more closely represents mathematical notation. Are there other programming languages that have this feature?
https://en.wikipedia.org/wiki/Miranda_(programming_language)
Hi everyone. I've recently contemplated the design of a minimalist, higher level Rust-like programming language with the following properties:
Clearly, mutable value semantics requires some way to pass/return-by-reference. There are two possibilities:
With most types in your program being comparably cheap to copy, making a copy rather then using an immutable reference would often simpler and easier to use. However, immutable references still come in handy when dealing with move-only types, especially since putting such types inside containers also infects that container to be move-only, requiring all container types to deal with move-onlyness:
len
or is_empty
on a container type need to use a reference, since we don't want the container to be consumed if it contains a move-only type. Being forced to use an exclusive mutable reference here may pose a problem at the usage site (but maybe it would not be a big deal in practice?)What do you think about having only exclusive mutable references in such a language? What other problems could this cause? Which commonly used programming patterns might be rendered harder or even impossible?
Subtyping is something we are used to in the real world. Can we copy our real world subtyping to our programming languages? Yes (with a bit of fiddling): https://wombatlang.blogspot.com/2024/11/the-case-for-subtypes-real-world-and.html.
How much progress have you made since last time? What new ideas have you stumbled upon, what old ideas have you abandoned? What new projects have you started? What are you working on?
Once again, feel free to share anything you've been working on, old or new, simple or complex, tiny or huge, whether you want to share and discuss it, or simply brag about it - or just about anything you feel like sharing!
The monthly thread is the place for you to engage /r/ProgrammingLanguages on things that you might not have wanted to put up a post for - progress, ideas, maybe even a slick new chair you built in your garage. Share your projects and thoughts on other redditors' ideas, and most importantly, have a great and productive month!
https://reddit.com/link/1h3fpg5/video/e1610wr9b24e1/player
the source code can be found at : https://github.com/oxumlabs/neit
update -> many new things have been added to lang which am not able to show here i woudl recommend you checking out the website to get full details (please note the site isnt the best and still needs improvemnts):
https://oxumlabs.github.io/nsite
I am thinking about a concept where it would be possible for a function to declare its return type to be automatically spread into its caller's scope upon return.
So that one could write a function which returns "...{a: number, b: number}"
A call to this function would then either return the object or void, but would insert "a" and "b" into the caller's scope.
Are there languages with support for this that I could look at for inspiration?
Never really paid much attention to Dart but recently checked in on it. The language is actually very nice. Has first class support for mixins, is like a sound, statically typed JS with pattern matching and more. It's a shame is tied mainly to Flutter. It can compile to machine code and performs in the range of Node or JVM. Any discussion about the features of the language or Dart in general welcome.
I'm thinking of adding a auto deletion for variable creation in my language, so you could say that it should be deleted after x retrievals or x seconds
The idea comes after I noticed that I had a private key that was read from a file while debugging, long after it being used
I was wondering if you guys have any option on this.
Here is a example of how it would look
- read private_key.txt into %key%, delete after 1st usage
// Use %key% variable
// %key% is no longer in memory
So now the line that creates the %key% variable is responsible for how it is deleted and I don't need to set it as null later
I'm starting to build my AST and have been keeping type information as a string. However, for array and dictionary literals, the type info is starting to get more complex. Should I include type information on my AST on the first pass, or is that something I should worry about later?
Right now I could create a string representation for an array of basic types e.g. `typeInfo="[int]"` or something similar, but an array of functions would get more complex especially if type inference is needed e.g. `typeInfo="[func(Int)Int]"` ?. Stringifying the type info immediately looks like a bad idea, so it seems a proper `TypeInfo` interface/struct is needed, but I'm wondering if I need to gather some information on the first pass and refine it later or completely deal with in later on a second pass or even maybe during the semantic analysis and remove the type info for now?
I found a very long time ago a website where you could download a grammar file from many programming languages, I remember to download there the VBScript language grammar definition.
If I am not mistaken, this website was part of a Windows software made to develop programming languages. Can you help me find this website?
I’ve tried a lot of frontend languages/frameworks: react js ts elm purescript svelte etc. but at some point i have no idea what i’m looking at. I could just be bad at coding, but when i look at projects github by nice people, i have to read a while before i understand what is happening and even then, when i read the code, i can only vaguely tell you what it is going to look like (except when they use a well known library without modification).
Back in html/css heavy pages with little javascript. I feel like it is easier to visualize what the thing will look like if i have the html and css side by side.
Then there is the concept of how coupled is semnatics with the design.
A lot of frameworks and languages have been made and so far i feel the main components they differ:
It would be my first time designing and implementing a language and i want it to transpile to html/css/javascript. I want to go about it from the ui-perspective. But i don’t really know what i’m saying, so i’m coming here for help and clarity.
What questions should i be asking? Is state management the hardest aspect? Merging markup-like with template-like syntax can be confusing to me (why use jsx if i can do functions directly? That’s a personal opinion maybe).
Thanks!
(Edit for clarity)
My lang has a normal syntax :
var i:int = 1 // decl
i:int = 1 // decl
i:int // decl
i = 2 // assign
Scoping is normal, with shadowing.
Now, since most statements are declarations and I am manic about conciseness, I considered the walrus operator (like in Go) :
i := 1 // decl
But what if we went further and used (like Python)
i = 1 // decl !
Now the big question : how to differentiate this from an assignment ? Python solves this with 'global' :
g = 0
def foo():
global g
v = 1 // local decl !
g = 1 // assign
But I find it a bit cumbersome. You have to copy the var name into the global list, thus changing its name involves 2 spots.
So my idea is to mark global assignments with 'set' :
var g = 0
fun foo() {
v = 1 // decl !
set g = 1 // assign
}
You'd only use SET when you need to assign to a non-local. Otherwise you'd use classic assign x = val
.
{
v = 1 // decl
v = 2 // assign
}
Pros : beyond max conciseness of the most frequent type of statement (declaration), you get a fast visual clue that you are affecting non-locally hence your function is impure.
Wonder what you think of it ?
I'm newer to rust, and using enums is a delight. I like being able to attach data to my enums, but how would this be implemented under the hood? I'm looking into adding this to my language, Luz