Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Haxe 4 changes, part 2 #387

Merged
merged 31 commits into from
Apr 22, 2019
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
2edbc3e
bump minimum PHP version
Aurel300 Apr 17, 2019
6828762
macro-in-macro
Aurel300 Apr 17, 2019
b6c3318
unicode support
Aurel300 Apr 17, 2019
2cc1715
wording
Aurel300 Apr 17, 2019
ad74dd4
consistent formatting in language features
Aurel300 Apr 17, 2019
e59613c
markup literals
Aurel300 Apr 17, 2019
c818270
haxe evolution link in markup literals
Aurel300 Apr 17, 2019
731601f
externs, @:native, implementing dynamic
Aurel300 Apr 17, 2019
716b35b
also mention new alternative to implements dynamic
Aurel300 Apr 17, 2019
2a07e61
lua-vanilla
Aurel300 Apr 17, 2019
2ddc701
sys and threading
Aurel300 Apr 17, 2019
a43c219
typos, untyped in type system, *.Syntax API
Aurel300 Apr 17, 2019
c80238a
warn-var-shadowing
Aurel300 Apr 18, 2019
789e115
long argument names
Aurel300 Apr 18, 2019
c138706
PHP defines
Aurel300 Apr 18, 2019
69471dc
target feature defines, .platform.hx files
Aurel300 Apr 18, 2019
7a203e0
jquery and swfobject in hx3compat
Aurel300 Apr 18, 2019
fe62c9f
hx3compat
Aurel300 Apr 18, 2019
fde8468
just utest
Aurel300 Apr 18, 2019
77ffdbe
@:using
Aurel300 Apr 18, 2019
1dd8e07
target-specific packages, *.Lib
Aurel300 Apr 18, 2019
34cf7f2
IDE integration, very shortly
Aurel300 Apr 18, 2019
f6edf72
fix link to vshaxe debugging info
Aurel300 Apr 18, 2019
0301d6e
null safety
Aurel300 Apr 18, 2019
14676cc
@:persistent
Aurel300 Apr 18, 2019
1806c1d
debugging attempt 3
Aurel300 Apr 18, 2019
3dbc36d
fix latex errors
Aurel300 Apr 19, 2019
d6bff6d
fix more (all?!) --switches, sorry simn
Aurel300 Apr 19, 2019
2871e94
review changes
Aurel300 Apr 19, 2019
633856e
remove reference to Safety library
Aurel300 Apr 19, 2019
c2a73ff
comment out markup section
Aurel300 Apr 22, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 1 addition & 14 deletions HaxeManual/02-types.tex
Original file line number Diff line number Diff line change
Expand Up @@ -722,19 +722,6 @@ \subsection{Dynamic with Type Parameter}
att.income = 0;
\end{lstlisting}

\subsection{Implementing Dynamic}
\label{types-dynamic-implemented}

Classes can \tref{implement}{types-interfaces} \type{Dynamic} and \type{Dynamic$<$T$>$} which enables arbitrary field access. In the former case, fields can have any type, in the latter, they are constrained to be compatible with the parameter type:

\haxe{assets/ImplementsDynamic.hx}

Implementing \type{Dynamic} does not satisfy the requirements of other implemented interfaces. The expected fields still have to be implemented explicitly.

Classes that implement \type{Dynamic} (with or without type parameter) can also utilize a special method named \expr{resolve}. If a \tref{read access}{define-read-access} is made and the field in question does not exist, the \expr{resolve} method is called with the field name as argument:

\haxe{assets/DynamicResolve.hx}


\subsection{Dynamic access}
\label{types-dynamic-access}
Expand Down Expand Up @@ -884,7 +871,7 @@ \subsection{Operator Overloading}

\since{4.0.0}

In addition to binary and unary operators, the \exrp{@:op} syntax can be used to overload field access and array access on abstracts.
In addition to binary and unary operators, the \expr{@:op} syntax can be used to overload field access and array access on abstracts.

\begin{itemize}
\item \expr{@:op([])} on a function with one argument overloads array read accces.
Expand Down
8 changes: 8 additions & 0 deletions HaxeManual/03-type-system.tex
Original file line number Diff line number Diff line change
Expand Up @@ -576,3 +576,11 @@ \subsection{Resolution Order}
\item For imports, a match is made if the name equals.
\item For \tref{static extensions}{lf-static-extension}, a match is made if the name equals and the first argument \tref{unifies}{type-system-unification}. Within a given type being used as static extension, the fields are checked from top to bottom.
\end{itemize}


\section{untyped}
\label{type-system-untyped}

\emph{Important note:} This syntax should be avoided whenever possible. The produced code cannot be properly checked by the Haxe compiler and so it may have type errors or other bugs that would be caught at compile time in regular code. Use only when absolutely necessary and when you know what you are doing.

It is possible to completely circumvent the type checker by prefixing an expression with the keyword \expr{untyped}. Any expression that can be parsed is then accepted and emitted into the generated output. This is primarily used with the target-specific \tref{code injection expressions}{target-syntax}.
Aurel300 marked this conversation as resolved.
Show resolved Hide resolved
9 changes: 6 additions & 3 deletions HaxeManual/05-expressions.tex
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,7 @@ \section{Blocks}
\paragraph{Variable Shadowing}

Haxe allows local variable shadowing within the same block. This means that
a \expr{var} or \expr{function} can be declared with the same name that was
previously available in a block, effectively hiding it from the further code:
a \expr{var}, \expr{final}, or \expr{function} can be declared with the same name that was previously available in a block, effectively hiding it from the further code:

\begin{lstlisting}
{
Expand Down Expand Up @@ -148,6 +147,10 @@ \section{Blocks}
}
\end{lstlisting}

\since{4.0.0}

It is possible that variable shadowing in code is unintentional. The compiler can be set to emit warnings about all instances of variable shadowing with the \expr{-D warn-var-shadowing} define.


\section{Constants}
\label{expression-constants}
Expand Down Expand Up @@ -282,7 +285,7 @@ \section{var and final}
var d,e = 2;
\end{lstlisting}

The scoping behavior of local variables is described in \Fullref{expression-block}.
The scoping behavior of local variables, as well as variable shadowing is described in \Fullref{expression-block}.

\since{4.0.0}

Expand Down
175 changes: 156 additions & 19 deletions HaxeManual/06-language-features.tex
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ \chapter{Language Features}

\begin{lstlisting}
#if js
js.Browser.alert("Hello");
js.Browser.alert("Hello");
#elseif sys
Sys.println("Hello");
Sys.println("Hello");
#end
\end{lstlisting}

Expand All @@ -56,9 +56,9 @@ \chapter{Language Features}

\begin{lstlisting}
enum Result {
Success(data:Array<Int>);
UserError(msg:String);
SystemError(msg:String, position:PosInfos);
Success(data:Array<Int>);
UserError(msg:String);
SystemError(msg:String, position:PosInfos);
}
\end{lstlisting}

Expand All @@ -72,7 +72,7 @@ \chapter{Language Features}

\begin{lstlisting}
for (i in [1, 2, 3]) {
trace(i);
trace(i);
}
\end{lstlisting}

Expand All @@ -83,7 +83,7 @@ \chapter{Language Features}
\begin{lstlisting}
var buffer = "";
function append(s:String) {
buffer += s;
buffer += s;
}
append("foo");
append("bar");
Expand All @@ -96,7 +96,7 @@ \chapter{Language Features}

\begin{lstlisting}
class MyClass {
@range(1, 8) var value:Int;
@range(1, 8) var value:Int;
}
trace(haxe.rtti.Meta.getFields(MyClass).value.range); // [1,8]
\end{lstlisting}
Expand Down Expand Up @@ -136,8 +136,8 @@ \chapter{Language Features}
\begin{lstlisting}
var a = { foo: 12 };
switch (a) {
case { foo: i }: trace(i);
default:
case { foo: i }: trace(i);
default:
}
\end{lstlisting}

Expand All @@ -147,11 +147,11 @@ \chapter{Language Features}
\begin{lstlisting}
public var color(get,set);
function get_color() {
return element.style.backgroundColor;
return element.style.backgroundColor;
}
function set_color(c:String) {
trace('Setting background of element to $c');
return element.style.backgroundColor = c;
trace('Setting background of element to $c');
return element.style.backgroundColor = c;
}
\end{lstlisting}

Expand All @@ -165,12 +165,25 @@ \chapter{Language Features}

\begin{lstlisting}
class Main<A> {
static function main() {
new Main<String>("foo");
new Main(12); // use type inference
}
static function main() {
new Main<String>("foo");
new Main(12); // use type inference
}

function new(a:A) { }
function new(a:A) { }
}
\end{lstlisting}

\emph{\tref{Markup Literals}{lf-markup}:}
Aurel300 marked this conversation as resolved.
Show resolved Hide resolved

Markup literals can be included directly in Haxe code, as long as they are processed by a macro:

\begin{lstlisting}
@:build(Component.build())
class MyComponent {
public function render() {
return <div>some <b>markup</b> with<br />some ${"haxe code"}</div>;
}
}
\end{lstlisting}

Expand Down Expand Up @@ -208,7 +221,7 @@ \section{Conditional Compilation}
\end{itemize}

\paragraph{Haxelibs}
By default, each used haxelib version is automatically added as flag, e.g. when you add \expr{-lib actuate}, the compiler adds \expr{-D actuate=1.8.7}. To test if a library exists in current context, use \expr{\#if actuate}. To check a specific haxelib version, use the operators, for example \expr{\#if (actuate <= "1.8.7")}
By default, each used haxelib version is automatically added as flag, e.g. when you add \expr{-L actuate}, the compiler adds \expr{-D actuate=1.8.7}. To test if a library exists in current context, use \expr{\#if actuate}. To check a specific haxelib version, use the operators, for example \expr{\#if (actuate <= "1.8.7")}

\paragraph{Built-in Compiler Flags}
An exhaustive list of all built-in defines can be obtained by invoking the Haxe Compiler with the \expr{--help-defines} argument. The Haxe Compiler allows multiple \expr{-D} flags per compilation.
Expand All @@ -218,6 +231,74 @@ \section{Conditional Compilation}
\item See also the \tref{Compiler Flags list}{compiler-usage-flags}.
\end{itemize}

\subsection{Target defines}
\label{lf-target-defines}

Depending on the current target, one of the following flags will be defined. Note that they are the same as the \tref{argument provided to the compiler to specify the output}{compiler-usage}.

\begin{itemize}
\item[\ic{as3}] Defined when generating ActionScript 3 code.
\item[\ic{cpp}] Defined when generating C++ code.
Aurel300 marked this conversation as resolved.
Show resolved Hide resolved
\item[\ic{cppia}] Defined when generating a cppia script.
\item[\ic{cs}] Defined when generating C\# code.
\item[\ic{eval}] Defined when running the code with \ic{--interp}.
Aurel300 marked this conversation as resolved.
Show resolved Hide resolved
\item[\ic{hl}] Defined when generating HashLink code.
\item[\ic{java}] Defined when generating Java code.
\item[\ic{js}] Defined when generating JavaScript code.
\item[\ic{lua}] Defined when generating Lua code.
\item[\ic{neko}] Defined when generating a Neko binary.
\item[\ic{php}] Defined when generating PHP code.
\item[\ic{python}] Defined when generating Python code.
\item[\ic{swf}] Defined when generating a SWF file.
\end{itemize}

Additionally, parts of code may be used in a macro context or during display completion. These flags can be used to check if this is the case:

\begin{itemize}
\item[\ic{display}] Defined when providing code completion.
\item[\ic{macro}] Defined in a macro context.
\end{itemize}

\paragraph{Supported features}

\begin{itemize}
\item[\ic{sys}] Defined if the target supports the \tref{sys API}{std-sys}.
\end{itemize}

\since{4.0.0}

To provide more fine-grained knowledge about the features supported on the current target without having to manually check which target supports what, Haxe 4 provides the \ic{target.*} defines:

\begin{itemize}
\item[\ic{target.static}] (or \ic{static}) Defined if the target is \tref{static}{types-nullability}.
\item[\ic{target.sys}] (or \ic{sys} as noted above) Defined if the target supports the \tref{sys API}{std-sys}.
\item[\ic{target.utf16}] (or \ic{utf16}) Defined if the target uses UTF-16 for its \tref{internal string representation}{std-String}.
\item[\ic{target.threaded}] Defined if the target supports the unified \tref{threading API}{std-threading}.
\item[\ic{target.name}] Defined to be the name of the target, e.g. \ic{js}.
\end{itemize}

\subsection{Target-Specific Files}
\label{lf-target-specific-files}
\since{4.0.0}

In addition to surrounding individual pieces of code with compile-time checks, it is possible to provide completely separate target-specific module alternatives to the compiler. This feature works as follows:

\begin{itemize}
\item When the compiler finds the file \expr{<Module>.hx}, it then checks the containing directory for a file called \expr{<Module>.<target>.hx}, where \expr{<target>} is the \tref{name of the current target}{lf-target-defines}.
\item The main file for the module (without a taget-specific extension) must exist.
\item If a target-specific file is found for the module, the main file is not loaded at all. Keep in mind that this means errors are not checked in the main file.
\end{itemize}

As an example, we can have the following directory structure:

\begin{lstlisting}
/somepackage/Example.hx
/somepackage/Example.js.hx
/Main.hx
\end{lstlisting}

In \ic{Main.hx} we can can use \ic{somepackage.Example} module. This module is defined in the file \ic{somepackage/Example.hx}. However, if we compile for JavaScript, the module is instead defined in the file \ic{somepackage/Example.js.hx}.


\section{Externs}
\label{lf-externs}
Expand Down Expand Up @@ -284,6 +365,38 @@ \section{Externs}
}
\end{lstlisting}

\subsection{Native Metadata}
\label{lf-externs-native}

When creating externs it is possible that certain fields will conflict with Haxe keywords, even though they are valid identifiers for the given target. These problems can be resolved by marking the conflicting fields with the metadata \expr{:native}, with the intended identifier provided as a parameter.

\haxe{assets/ExternNative.hx}

The generated JavaScript output shows that we are actually assigning to the \expr{final} field:

\begin{lstlisting}
(function ($global) { "use strict";
var Test = function() { };
Test.main = function() {
new A().final = 3;
};
Test.main();
})({});
\end{lstlisting}

This metadata can be applied to class and interface fields, but not the fields of a structure type.

\subsection{Implementing Dynamic}
\label{types-dynamic-implemented}

Extern classes can \tref{implement}{types-interfaces} \type{Dynamic} and \type{Dynamic$<$T$>$} which enables arbitrary field access. In the former case, fields can have any type, in the latter, they are constrained to be compatible with the parameter type:

\haxe{assets/ImplementsDynamic.hx}

Implementing \type{Dynamic} does not satisfy the requirements of other implemented interfaces. The expected fields still have to be implemented explicitly.

\trivia{Implementing \type{Dynamic} on non-externs}{Starting with Haxe 4, implementing \type{Dynamic} is only allowed on extern classes. In previous versions any class could implement \type{Dynamic}, allowing arbitrary fields to be read or written. Additionally a special \expr{resolve} method could be used to resolve read access to a non-existend field. A similar feature is now available as field access \tref{operator overload}{types-abstract-operator-overloading} on abstracts.}


\section{Static Extension}
\label{lf-static-extension}
Expand Down Expand Up @@ -834,3 +947,27 @@ \section{Inline Constructors}
var pt_y = 9.3;
};
\end{lstlisting}


\section{Markup Literals}
\label{lf-markup}
\since{4.0.0}

Haxe supports markup literals embedded directly in the code. This can be used to implement domain-specific languages (DSL), component libraries, heredoc strings, as well as other declarative syntax. All markup literals must be processed by a macro function. This avoids the issue of having a ``default'' meaning to a markup block and instead allowing macro writers to interpret these fragments any way they see fit.

\haxe{assets/Markup.hx}

It is important to note that this syntax is not XML. The contents of the enclosing markup tags can be completely arbitrary, as long as they do not interfere with the closing tag. The processing macro simply receives an expression (\type{haxe.macro.Expr}) containing a string constant that is annotated with a \expr{:markup} metadata.

Tags can be nested inside the markup, as long as they are correctly terminated. This introduces some limitations on self-closing tags:

\begin{lstlisting}
// this markup literal parses correctly:
<div> <div> <div></div> </div> <div /> </div>
// as does this one (even though it is no longer valid XML):
<div> <div <div></div> ></div> <div /> </div>
// but this one causes a parsing error:
<div> <div <div></div> /> <div /> </div>
\end{lstlisting}

\trivia{Haxe Evolution proposal}{This feature has been originally proposed by Juraj Kirchheim in a \href{https://github.com/HaxeFoundation/haxe-evolution/blob/master/proposals/0006-inline-markup.md\#inline-markup}{Haxe Evolution proposal}.}
Loading