HTML, CSS, JavaScript, PHP and so on were brilliant when they were invented for the needs of their time three decades ago.
But as they grew and new complex challenges arose things got messy and unnecessarily complicated.
Sometimes I had to maintain files with 4 different coding languages intertwined with each other.
The main crux was that this took out my joy of programming.
Therefore, I came up with the concept of WY (pronounced "Why") with the approach of "What would I dream of" - a web programming language for markup, style, and client/server applications.
It leverages the best of Python, C/C++ and Java. WY's core principles are:
Principles of WY
@Element/Layout-principle
Instead of thinking like "Microsoft Word", think like "Adobe InDesign" or element-based UI/UX design tools.
When bandwidth was very low, web pages were text-oriented (HyperTEXT Markup Language), sometimes spiced up with an image. But today websites look completely different. So I believe it's important to think like a web designer to create a new web language.
Otherwise, we try to force them to use inappropriate tools and materials. Then the result may look nicely painted, but inside it's a chaotic dump.
Showcase
Personally, the most efficient way to learn a new programming language is to look at example code. Since one of the principles of WY is intuitive readability, I think it's best to show it to you with some comments.
class ColorButton(color) extends Button
{
// color (object property) is automatically set to
// the value of color in the parameter list, as it has the same name.
text = "Press"
clicked() // Overwrite method
{
MessageBox("Hello World!")
}
}
server // The code in this block is executed on the server side.
{
title = "Hello World!"
canvasMode(ABSOLUTE)
execute("standardDesign.wyx") // Sets the default spacing of
// the boxes, fonts etc.
// .wyx is a compiled .wy file
// .wyb is bytecode
// .wy is script
}
client // The code in this block is executed on the client side in the browser.
{
{ // This block creates an instance of an anonymous object
x = 100 // and attaches it to the DOM tree.
y = 100
text = "Hello World!"
width = 300
height = 300
Subobject // Subobject is the name of the object declared here,
{ // it is created and added to the DOM tree.
x = 10 // The X coordinate is relative to the parent object.
// The Y coordinate is 0 by default.
text = "Subobject"
}
}
setCursor() // This function sets the **object cursor** to the last created object
// in the current {}-scope. The subsequent created objects are attached
// as children of this anonymous "Hello World" object. They are located
// in the layout within this object.
// Instead of setCursor you can simply write >
> 10, 90 px // This moves the object cursor to position 10, 90 px within the object.
ColorButton(#667788) // This creates an instance of the ColorButton
// at position 10, 90 px within the "Hello World" object and
// attaches it as a child element.
> Subobject // From now on, all subsequent objects created will be attached to
// SubObject as children.
> 30, 30 px // This moves the object cursor to position 10, 90 px within Subobject.
ColorButton(#115588)
}
Or another example:
MainContent
{
x = 30
y = 50
textStyle = FormatObjectNormal // The text style is defined by assigning a
// formatting object.
ImgPortrait
{
// x and y are automatically 0.
image = "portrait.jpg"
margin = 10
}
subtractFormText(ImgPortrait) // Here the shape of the image is subtracted from the
// shape of the text field. The result is that there is
// no text where the image is, as if the text field had
// been cropped in a layout program. This example
// demonstrates the layout-centered approach.
text = "Lorem **Ipsum** // The formatting in the text is similar to Markdown.
Dolor bla bla // Fancy formatting is realized with a formatting object.
Lirum
!%Formatobject2('Larum Löffelstiel')!
...
[Books](https://search.worldcat.org)^" // ^ opens the link in a new tab or window.
}
More Features
class Fruit<type>
{
//...
}
class Apple extends Fruit<int16> // Inheritance from a Fruit with int16 as type
{
//...
}
class Robot
{
Robot() // Constructor
~Robot() // Deconstructor
*Robot() // Class constructor
~*Robot() // Class deconstructor
}
Safety / Referencing Variables
One of the most dangerous sources of bugs in programming are memory access errors. In WY this is solved as follows.
Referencing variables in the code are already checked by the compiler/script verifier when they are accessed to see if they have been checked for null by using safe.
If this is not the case, a warning is issued. (Normal object variables are not referencing variables).
When parallel threads are running, it's important that the target of the referencing variable is not deallocated when the referencing variable is in use. The safe block ensures this.
Planet &curPlanet, // This is a referencing variable. It is set to null by default.
venus,
mars
curPlanet = venus
safe(curPlanet) // This checks if curPlanet != null.
{
// If any parallel code tries to deallocate venus, the deallocation is
// halted until the safe block is finished.
free venus // This would cause a deadlock! The program would not be continued.
}
else
{
// This code block is executed if curStar is null.
}
free venus // venus is deallocated and set to null. Therefore curPlanet is
// also automatically set to null.
If the target of a referencing variable is no longer valid (its memory has been deallocated), the referencing variable is immediately and automatically set to null during runtime. WY keeps a table in the background with all referencing variables and their targets.
Referencing Variable | Target | isSafe |
curPlanet | venus | 1 |
This mechanism prevents memory access errors.
Maybe this draft could make life a lot easier. 🙂 ☕
(If you would like to buy me a coffee for my efforts, you can do so at https://www.buymeacoffee.com/mutzu.)