Hacker News new | past | comments | ask | show | jobs | submit login
New embedded programming language with C as a host language (vely.dev)
95 points by dsvr on July 25, 2022 | hide | past | favorite | 68 comments



Sergio here, the creator of Vely. Go ahead and roast it. Here's a brief from the front page:

Vely is an embedded programming language with C as a host language. It's precompiled into C, creating a native executable.

Vely empowers C with rich features, simplicity and enhanced safety. It is general-purpose and well-suited for web applications.

Use Vely to rapidly develop high-performance and low-footprint applications


I think I like the idea but I have a really hard time figuring out what exactly the code is doing. This is in contrast to say (in my experience), jsx - where what's going on is quite obvious, or zig, where for the most part it's clear what "the equivalent c would be".

I apologize, I don't have specific feedback beyond a vague sense of mild confusion or constructive ideas on how to make it better, hopefully someone else brighter than I can take a crack at it?


Thanks for your feedback. You can see the equivalent C code for any statement pretty easy. For example, if you go to "tutorials", then "tutorial-stock_app", and follow the tutorial instructions, you can always see the generated C code, which would be in:

  /var/lib/vv/bld/stockapp/__stock.o.c
(so here "stock" is the application name and there's "stock.v" file).

For example, when you see this Vely statement in stock.v (which obviously obtains input parameters from either GET or POST request):

  input-param stock_name
this is line 9 in stock.v.

All you need to do is look for:

  #line 9 "stock.v"
in the generated code (which is /var/lib/vv/bld/stock/__stock.o.c), in this case it's:

  char *stock_name = vey_get_input_param (vey_get_config()->ctx.req, "stock_name")
So in this case, it's just one line of C code. In other cases, it may be many lines. For example, Vely statement which apparently runs the INSERT SQL query:

  run-query#add_data@db = "insert into stock (stock_name, stock_price) vaues ('%s', '%s') on duplicate key update stock_price='%s'" : stock_name, stock_price, stock_price
This is on line 12 in stock.v, and you can simply search for

  #line 12 "stock.v"
in /var/lib/vv/bld/stock/__stock.o.c file. In this case, the generated code looks like:

  VV_UNUSED (_column_count_add_data);
  vely_get_config()->ctx.db->ind_current_db=0;
  static void *_sql_prep_add_data_stock_v_649 = NULL;
  _is_input_used_add_data[0]=1;
  _is_input_used_add_data[1]=1;
  _is_input_used_add_data[2]=1;
  add_data = "insert into stock (stock_name, stock_price) values ('%s', '%s') on duplicate key update stock_price='%s'";
  const char *fname_loc_add_data = "stock.v";
  num lnum_add_data = 12;
  vely_location (&fname_loc_add_data, &lnum_add_data, 1);
  vely_make_SQL (&_sql_buf_add_data, 3, add_data , _is_input_used_add_data[0]==1 ?  (stock_name) : NULL , _is_input_used_add_data[1]==1 ?  (stock_price) : NULL , _is_input_used_add_data[2]==1 ?  (stock_price) : NULL );
  if (_qry_executed_add_data == 1) {vely_report_error("Query [add_data] has executed the second time; if you want to execute the same query twice in a row without a loop-query, use different queries with the same query text (or variable) if that is your intention, file [stock.v], line number [12] ");}
  _qry_executed_add_data = 1;
  vely_execute_SQL (_sql_buf_add_data, &_arow_add_data, (const char**)&_err_add_data, (const char**)&_errm_add_data, 0, 1, 0, &_sql_prep_add_data_stock_v_649, _sql_paramcount_add_data, _sql_params_add_data);
  _nrow_add_data=0;
  vely_db_free_result ();
  vely_free (_sql_buf_add_data);
so about 16 ines of code.

This way you can see what actual C code is generated for any Vely code.

And you can also step through this code in gdb by using --c-lines option in vv.


Maybe you should show more bite-sized simpler examples?

There is a lot going on in your big example, and I wouldn't want to have to download and run it first to get a rough mental model of what's happening.


I see your point. That's something to add to the documentation. For now, I guess, here it is. Each Vely statement generates some C code, maybe a one-liner, maybe quite a few. It works kind of like a declarative statement, SQL comes to mind. Some clauses in a Vely statement are input data, others are output. The generated code will take the input and fill in the output.

And Vely generates a request dispatcher, which takes the "req" input parameter, which is really the name of the source Vely file. So if "req=mycode", then the function "void mycode()" will execute and it must always be defined in source file mycode.v. This makes it easy to always find the code, and quickly grasp what application does.

Unlike C Makefile, you don't have to write a Makefile. Whatever .v files you have in your source code directory will be automatically picked up and made into an application.

The generated code can and will change. It tries to do the best job of doing what is instructed to do. So if you say:

  web-call "http://website.com" response resp response-code rc status len post files "file1"="uploadtest", "file23"="fileup4"
then it will generate the C code to effectively POST a form to website.com that sends two local files to that server, and will get you the response code and status back. You can do this by using CURL library, but it will take quite a bit of C coding to do this. And there are many different combinations and things you can do, and the code gets generated to do it quickly and efficiently.

The same goes for exec-program, run-query, send-file, encrypt-data etc etc. All this things you can program yourself in C, but these statements are flexible and will let you quickly and safely do those things. More like "what I want to do" rather than "how I want to do it". Though, like I said, you can examine the generated C code to see exactly how it's done.

The "hello world" tutorial is good for this. And if you do decide to try Vely, I would say try

  https://vely.dev/123_hello_world.html
first, as it can't get any simpler. It's designed to give you an application in minutes. You'll get a command-line executable, and you will be running your own application server that can take input from Apache or Nginx via FastCGI. The example though uses FastCGI command line client so you don't have to do anything beyond what's already included in Vely package.


This description as is should be on the front page.


I've incorporated it in "In a nutshell" section on the front page. Hope it helps people get what Vely does right away.


Thank you for this feedback. I really appreciate it. I will incorporate it prominently on the web site.


Figured out on the fly hackernews markdown. Pretty neat.


I like the premise of embedded generating inline c. Kinda like php for c, rather than html

I'm not sure of custom BNF per generating command. I notice they're mostly order independent, which makes it a little easier to learn, but what's the advantage over c syntax? Is it roughly that pointers etc are impossible. Maybe a c-esque syntax would be more learnable

How does the existing syntax compose, i.e. can the user run away with writing tcl-style scripts

If you don't get a lot of feedback, I would guess it is inpart due to custom syntax being an entry barrier to understanding

I don't know, I think html is easy, so people want power with php. On the other hand for an audience that is using c, by the time I'm doing that, does Vely's custom syntax give me more than a set of convenient c library calls... such as https://kristaps.bsd.lv/kcgi/

In any case, I like the apis, and aim, and I think the premise has legs


I looked at kcgi and it's pretty cool for CGI/FastCGI if you want a-la-carte and then you use separate libraries for everything else.

Vely has FastCGI built in by default (you can start FastCGI server in seconds with vv/vf), and the output statements (such as @ or p-out) do output to the web (i.e. to the Apache or Nginx reverse proxy) by default.

So you could say in terms of functionality, kcgi is built into Vely transparently.

In terms of additional functionality beyond kcgi, Vely offers

- web constructs (getting input parameters from GET/POST, uploading files, sending files to client with send-file, cookie handling, output to web etc.),

- safer and easier string manipulation,

- database access (mariadb, mysql, postgresql, sqlite) with prepared statements and persistent connections,

- regex (match-pattern),

- exec-program for executing programs,

- file operations,

- encryption/encoding/hashing.

I agree there's a learning curve. I can't say how would people see that, though the idea is to be easier than a traditional API, simply on the account of writing a single statement instead of say 5-10 C API calls.


Thanks for the feedback. The clauses in statements are not order dependent, so they can be specified in any order. No need to remember what goes where, just splatter your thoughts out.

Vely is meant to be more human-readable than APIs; it leans more declarative than API. Each statement typically does what a number of C API calls would do, so the idea is to save time by saying what you need done rather than placing a number of API calls. At the same time, it's safer because it handles all the details and has a memory garbage collector.

For instance, web-call does all kinds of GET and POST calls. run-query does SQL queries. write-string composes complex strings. Etc.

Vely is also a thin framework. You can fire up FastCGI application server in minutes, and use the same program to run a command-line program.


Maybe, rather than php, a "reactjs for c" is the direction you're heading


Interesting thought. Yes, it makes writing applications, easier, it inherits the top performance of C, it's got a lot of rich functionality.

Vely is also a thin framework that mostly helps with building apps by not having to write Makefile, it will pickup any .v files you got.

And it will generate a dispatcher for requests.

But the framework doesn't do much, only the essentials, and that's by design. After all, C is all about flexibility, and that stays.


and roast it

hopefully not although Slor HN could be a variant of Show HN but for roasting.


I am into grilling and griddling and cooking, so comes natural to me :>


Many new safer-than-C system languages will know what it is to be roasted in the depths of the Slor that day, I can tell you.


> It's precompiled into C, creating a native executable.

This reminds me of Bjarne Stroustrup's original implementation of C++ which was also transpiled to C. That was known as "Cfront" compiler at the time.


Yes, kind of, you're right. C++ though went on for a roller-coaster of complexity, at least that's how I see it.

I think of Vely as staying simple, declarative, and C all the way for performance reasons. More of a collection of practical things you'd want to do.


Nim does the same thing.


The less celebrated Vala language, too.

https://en.wikipedia.org/wiki/Vala_(programming_language)


Please change

  code {
    font-family: 'DejaVu Sans Mono';
  }
in your CSS to

  code {
    font-family: 'DejaVu Sans Mono', monospace;
  }
For people without DejaVu Sans Mono installed (or for browsers doing a good job at defeating font fingerprinting), which would be most people, the code sample is rendered in the default proportional font, which is very ugly.


How about:

  font-family: monospace;
and that's it.


I found DejaVu Sans Mono to be a bit thinner and easier on the eyes. Either way is fine really. One of those whimsical decisions, I guess.


So change the monospace font in your browser.


Could this not be said about any stylistic choice though? Why should websites pick their own heading weight? What's wrong with the default text colour? Who are you to tell the browser not to use the default padding?

People have been mucking about with typography since Gutenberg's day and they're not going to stop now.

I'm personally 'font blind', but I don't have a problem with people being creative and making aesthetic choices.


While I'm totally on board with you on the principle that a website should inform the browser what is, not how to show it, that particular site is hardly the place for this discussion...

_ANY_ article about CSS and client side javascript however.. go go go! :)


DejaVu Mono is also my preferred monospace font. Have tried some other popular ones but always returned to it.


It is fixed. Thanks again.


Great suggestion, thanks. Will do.


Without a value judgement here is my analysis. It bears an unexpected similarity with PHP/FI 1.0, where a limited set of extended statements are mixed to the base language (which is HTML in PHP/FI and C in Vely). I had a gut reaction that memory management would be problematic, and Vely "solved" it by implicitly owning all memory allocated by Vely statements and deallocating them at the end of the current request. If my understanding is correct, vv doesn't seem to fully understand the C-plus-Vely language and just detects Vely keywords from C tokens [1], and I don't think it's a good idea.

[1] https://vely.dev/language_statements.html "Note that, Vely statements, after translated into C code by vv, are generally made of multiple C statements, hence Vely statements can never be treated as single-line statements." (suggesting that there is no full parser for C-plus-Vely)


Thanks for the feedback, I appreciate it. Yes, Vely does not parse C. Placing Vely statement outside of functional context (say in between functions) will result in gcc errors. Vely allows error reporting to show both generated C or line numbers in Vely code, so depending on what the error is, it's not that difficult to find.

Making Vely understand C, at least insofar as necessary to prevent issues like this is something that I might add, and it probably wouldn't cost that much. It's definitely worth a look.

From a purely functional perspective, assuming Vely statement is placed properly in a functional context, understanding C (as in parsing and then parsing Vely within) might not bring much benefit. Syntactically speaking, Vely is built to not require much about host language. Though, Vely understands enough to emit meaningful messages, such as in the case of writing:

if (cond) vely_statement

where you will get an error that will prevent code from doing unexpected things. There's quite a few of those safeguards built-in.

Being embedded, Vely is a compromise. That was the goal to preserve pure C performance.

Beyond the above, one can still do anything that C can do and that may not be safe; but if Vely is used for what it does, the chances of that go down. Being able to rapidly do stuff in C that is richer and safer is the plus side of it. Without a compromise with being embedded, it would be yet another language that does everything great but with ever declining performance.

And that is fine, if such loss of performance and increased footprint is acceptable; there is nothing wrong with that. Vely's niche is to stay in best performance bracket, and yet bring that performance to general and web application development.


It seems like what i imagine a cython poc looked like, plus html?


I guess you could see some similarities. Vely is standalone though, not an extension. And it is 100% C, always creating native executables.

By that I mean a direct native executable from either pure C or embedded statement producing shallow and performant C, without layers of other languages intertwined (because in the end anything is always a native executable even if it has layers of byte codes, interpreters, alone or mixed with native extensions).


But I guess from a bird's view point, I can see how all the impressions given here are correct. It does look somewhat like PHP for C or like a markup language, or a declarative language etc.

There's some truth to all of that to some extent.


Unless I'm reading this wrong, Vely doesn't actually understand C, correct?

This means that all the diagnostics being emitted will be very confusing. When incorrect input is given, Vely doesn't produce the error message, gcc does, which makes it difficult to match the error message to what the user actually typed in.

I've used (and created many[1]) "embedded" languages, and this is the biggest problem with those that simply do pattern matching and replacement: the language the programmer is writing is unaware of errors and the programmer has determine what they did wrong by looking at the generated code.

It's not a big problem if the programmer understands this limitation; that the "language" is a macro language that blindly transforms input to output with no understanding of the input. If the programmer accepts this, it can be very useful.

[1] I just created a html preprocessor in bash this morning. It performs variable substitution using environment variables and runs the C preprocessor on the input, allowing #include directives, #ifdef, etc. It lets me write my HTML files in fragments that can conditionally include other HTML files, and it lets me put in variables in the HTML file that are substituted with values from the environment.

I've no doubt that this is a hacky solution, but

a) It took only an hour to write (thus far - there's some TODOs in there for stuff that might be useful in the future)

b) It was quicker than downloading and learning to use an existing tool that does the same thing, and ensuring that all that tools dependencies are brought in as well.


No, Vely does not understand C. Yes, gcc produces error messages when it comes to C code itself. However, the line number where the issue is located is exactly matched to the Vely source code using #line directive, so I would say 90+% of the time you don't have to look at the generated code. If that is not enough, you can use --c-lines to get the error reported from generated code, which is the exact error, and in that case, yes like you said you need to look at the generated code. Most of the time, however, just looking at the exact embedded statement is enough to figure out what the problem is.

I mentioned in another post that a C program could be parsed to the extent to allow better checking. Not to the point where you'd build a gcc-look-alike, but just enough for instance to know the type of the expression, and if the expression used in Vely statement is correct, and such. Perhaps that's something to consider. I thought about it here and there, but found it to be more useful to check for logical conflicts, such as not providing required arguments, balancing beginning and end of multi-part statement, incorrect usage and such. Typically, using the wrong type accounts for most of the issues, and gcc produces very good messages. Again those messages get matched to the source Vely file exact line number, and I found that correcting an issue isn't difficult.

Your tool sounds great, and if it works what you need it do, awesome! I do things like that all the time, and find that often times using tools is an overkill, and just skip it. There's time and place for everything.


TBH, I wasn't concerned at all about matching errors to line numbers (I didn't mention matching up the line numbers because I assumed it would anyway); I've done this sort of thing before and never had a problem setting the correct line numbers in the outputted C sources.

The problem I usually have is matching C-compiler error messages to $NEWLANG errors.

Like I said, as long as the programmer is aware that it's a preprocessor for the language and not an AST-based code generator, then there usually isn't a problem. I used ecl (or gcl, not sure now) that went the AST code-generation path and it worked much better than any preprocessor-based method in terms of compilation errors and diagnostics.

PS. In case you (or anyone else) is wondering about my mentioned HTML preprocessor, I put it into a gist: https://gist.github.com/lelanthran/603a24c56bc3afc1370a007a0...


Actually for someone using C only for microcontroller, it is an interesting approach.

Hardware drivers, like USB, SPI, etc could be done in C and wiring up things and pushing data around in a more high level language.

After considering micropython for exactly that purpose, I was disappointed because of the implementation complexity and slowness of computations on that platform.

What are your thoughts on this?


You could use Nim [0] for this purpose. It looks like Python, compiles to C and there are people doing embedded stuff in Nim [1].

[0] https://nim-lang.org/

[1] https://github.com/dinau/nimOnAVR


C++ has decent industry acceptance in embedded nowadays, or at least that has been my impression.

After C++, rust is likely the most popular, quite a lot of effort has been put into running rust on embedded, see eg https://github.com/rust-embedded. However, once again to my understanding, industry acceptance is still highly marginal.

After that, there's a bunch of toy-ish efforts to run other languages. Zig, nim, python and javascript variants, etc. Usually anything that has C ABI compatibility should be possible to get up and running (without writing a compiler backend from scratch). I've had fun with some toy projects using nim for ARM cortex-M targets (https://github.com/EmbeddedNim/svd2nim, https://github.com/auxym/nim-on-samd21, https://github.com/EmbeddedNim/picostdlib).

Using Nim (and eg svd2nim to generate the equivalent of CMSIS headers for register access in pure nim), it would be entirely possible to write even the low level stuff (SPI drivers and whatnot) in 100% nim, with the same performance as C and better safety (better static type system and compile-time checks, etc). Runtime (eg overflow) checks and garbage collection are available (at the cost of some performance) but optional. See eg. a pretty basic higher-level API for GPIO access, that provides native performance, since the abstraction is implemented as macros (compile-time abstraction): https://github.com/auxym/nim-on-samd21/blob/master/src/port....


That is one of the use cases I would say are perfect for Vely. A combination of a low-level and high-level approach, which is often needed, and not just in this arena.

IOT (Internet Of Things) is a major application area for Vely. Obviously what you mentioned may fall into that. But also for example IOT-edge systems, where the communication with multiple near-devices converges, gets processed and then delivered to a cloud server for congregation.


Nim does the same but with a Python-like syntax.


What is this language's approach to memory safety? Does it guarantee there can never be out of bounds accesses, use after frees, double frees, or other memory corruption errors? Anything which talks to attackers over the internet is a prime target for these sorts of attacks.


Vely statements are created to generate safe code that will take care of memory issues you mentioned. It's like using a library that does something for you safely, except that Vely provides an interface that is more flexible and easier.

The trick is for Vely to be rich enough to provide the functionality that's typically needed. That is its goal. I hope it's far enough along to be useful, and with time it will get even more so.

Generally, the memory used by Vely statements is created by Vely and you don't have to free it, in fact you shouldn't, it will be freed automatically, even if those pointers are lost or overwritten. The approach is to drastically minimize using C's allocation, and do that only when absolutely necessary, which for most applications should be never.

However, you can still write any C code that does horrible things with memory. Vely exists so you don't have to. The idea is to use Vely to write code that you might otherwise write in pure C and have those issues.


FYI the hello world example instructions border on unreadable on a phone due to the indentation

https://vely.dev/example_hello_world.html


I changed the indentation of lists to be smaller. At first just for mobile via media CSS, but then it seemed more readable for desktop too. So it should look better now.


Thanks a bunch! I will look into this.


I know it's just an example, but querying database, saving to file, displaying web page - all in one function - reminded me of old big-ball-of-mud PHP codebases.


Ha ha, okay you got me. It's a piece of code that is for demonstration only. But I needed a simple piece of code that speaks of shrinking, without making the front page an exercise in design patterns.


How about releasing Vely as both a standard c library and...

A syntax preprocessor that can be generically applied to multiple libraries


That is a very interesting suggestion. The API underneath is already well-defined and documented in code. Something to consider for sure.


Please stop reusing extensions. “.v” is already used by Coq and by V.


At the time I didn't know that. Perhaps .vely extension, I guess that would do it. Something to consider to be nice for sure. Thanks for that.


And Verilog. Not that it matters much since tools can utilize heuristics to figure out the actual language used.


How do you use heuristics when creating a new file?


In this case, just check if there is, near the beginning of file:

#include "vely.h"

which has to be in every Vely .v file.


A new file won't have that at the top. Unless you create it first by copying a template, I guess.


And Verilog


Somewhere between PHP and Objective-C?


I guess you could say that. Quite a few comparisons here, and none really wrong as it's all in the eye of a beholder. Vely's main goal is to give you building blocks for general purpose application development, especially including web applications.


Vala, Vale, Vely, and others?


There is also Vlang (https://vlang.io/), which has C interop and can be compiled into C. In addition to it being both a Go and C alternative language, that has high readability and usability, to include being able to use it like a scripting language.


I didn't know about Vlang, I checked it out, looks very cool.

Vely is really not a language breakthrough. Not at all.

I would say Vely is a practical workhorse. It is about power of rapidly doing business. Kind of like PHP but more in a declarative way like SQL, within C.

As in, you need a collection of libraries that do all the stuff you need to build an application (run queries, build strings really easy, execute programs, do web calls, deamonize programs etc.).

And you need it without writing C code or using API or procuring libraries and header files, but rather you'd just spill your thoughts about what to do in a language that sounds like a natural language, where even the order of how you say it isn't that important.


A fair review for readers information: https://mawfig.github.io/2022/06/18/v-lang-in-2022.html


You are just spamming that negative hit and run smear job, which is being used as a new weapon (linkable smear document) by detractors and competitors, that was made by a user with a throwaway account. The purpose is to keep attempting to spam it, including other negative slander of the author or smearing of the language, all over the internet (HN and other sites). There is nothing "fair" about such hit jobs, nor was it ever intended to be.

They made that one post on GitHub and ran. With no intentions of updating it or correcting its errors, not to interact with anyone, nor to review any other programming languages.

It even refers to an older version of V (0.2 versus 0.3), with various issues that are not even relevant anymore or are their bias one-sided uneducated opinions. It purposely gives readers no balance or an opposing perspective, and is presented with no feedback from Vlang's developers or community (despite having a GitHub account).

Oddly, your account's history and purpose seems to be super laser focused on specifically attacking and trolling anything referring to Vlang.


"Vely" stands for Vel(ocit)y. Though I then realized in Korea it's short for Lo(vely). Could be worse.


Valley, very, vary.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: