Giter Site home page Giter Site logo

jfecher / ante Goto Github PK

View Code? Open in Web Editor NEW
1.8K 31.0 74.0 38.94 MB

A safe, easy systems language

Home Page: http://antelang.org

License: MIT License

Rust 95.05% Scala 4.34% Dockerfile 0.02% Nix 0.59%
compiler language systems-language refinement-types llvm ante

ante's People

Contributors

0b01 avatar arbilgit avatar bisen2 avatar dependabot[bot] avatar ehllie avatar iacore avatar jbaa avatar jennycpero avatar jfecher avatar kevaundray avatar mkhan45 avatar mtshiba avatar nrabulinski avatar thehabbos007 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ante's Issues

obj/parser.d: No such file or directory

ante (master??!)  $ make
Generating parser...
In file included from include/parser.h:8:0,
                 from include/ptree.h:4,
                 from src/syntax.y:8:
include/compiler.h: In member function ‘int DataType::getFieldIndex(std::__cxx11::string&)’:
include/compiler.h:56:26: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         for(int i = 0; i < fields.size(); i++)
                          ^
src/parser.cpp: At global scope:
src/parser.cpp:4734:1: fatal error: opening dependency file obj/parser.d: No such file or directory
 } // yy
 ^
compilation terminated.
Makefile:43: recipe for target 'obj/parser.o' failed
make: *** [obj/parser.o] Error 1

system:

Linux mint-kitty 4.4.0-23-generic #41-Ubuntu SMP Mon May 16 23:04:25 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

global variables

Will there be possibility to disable use of global variables (dangerous ones, modified during runtime)? Either per project or when a module is imported.

String length overriding tuple in union

Using the same code as #39 , but replacing with a tuple match and extract:

Printing the value of the u8 in Some always gives the length of the string, and not the value passed in to the constructor.

llc stall with functions returning non-constant tuples

When given bitcode containing a function returning a non-constant tuple, llc stalls and exponentially increases memory usage. This does not seem to occur if all elements except for the last is constant in the returned tuple. Example problem code:

i32,i32 toTuple: i32 a b
return (a, b)

let tup = toTuple(2, 3)

When a tuple of four or more elements is returned instead, instead of llc stalling, the optimization passes for the function crash instead. The specific pass that crashes is:
X86 DAG->DAG Instruction Selection

Problem making...2 versions of LLVM

I was not able to make Ante...when I looked at pacman on arch, it clearly showed as having LLVM 3.9.1 installed.

But when I did lli --version, the version I got back was 3.6.2.

I found out 3.9 is installed in /usr/bin while 3.6.2 is installed in /usr/local/bin.

I've not been able to find how to either remove 3.6.2, or set it up so that 3.9.1 gets used instead.

Any pointers would be greatly appreciated....no pun intended.

Segfault on type-parameter compile

Maybe I'm misunderstanding some basic syntax here

type Box<'t> = 't contents
printf "%d" (Box 1u8).contents

This program segfaults at compFnCall line 1001, apparently because val is NULL on a TypedValue.

Interestingly, this doesn't happen if you leave out the printf - just (Box 1u8).contents compiles fine. Could this be an issue with the type inference?

name could bear some semantic meaning

Currently name is just a text and what characters it contains doesn't matter to the compiler, as long as they are from valid range.

How about possibility, to specify in project configuration that certain format of names implies certain property of its bearer.

Few examples:

  • if name ends with ? it is bool variable or function returning bool. Spaniards may want ¿ at the beginning and ? at the end.

  • if function name ends with ! then it means the function has no side effects

  • if someting is a macro it may start with #

  • private names start with lowercase, public with uppercase (ala Go).

stdlib and 3pp sources may get preprocessed and characters not specified in project config preprocessed out, lowercase/uppercase replaced by pub/priv, etc.

These things, rules of formatting and naming, may sound trivial, but they are often contentious and deter people from reusing other's code, "because ugly and nonconforming".

Support for functional style

For me, functional style primarily means "function uses only immutable parameters, doesn't touch anything global". Wouldn't it make sense to support this functionality by the language?

Specifically:

  1. Definition of such function could be distinguished from ordinary impure function. E.g. fn instead of fun, or having proc and fun or something.

  2. Invocation syntax. It should be clear on the first sight that a pure function is being called, not an ordinary one. E.g. using double parenthesis for such call, my_fun((par1, par1)), or inverted parenthesis, my_func)par1, par2(, or something.

link error for "hello world" test program

I am not sure on if this is an error or if I am doing something wrong:
$ cat test.an
print "Hello World!"

$ ./ante_x86_64_unix -r test.an
/usr/bin/ld: test.o: relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
sh: 1: ./test: not found

ubuntu 16.10
$ ldd ante_x86_64_unix
linux-vdso.so.1 => (0x00007ffe3e717000)
libLLVM-4.0.so => /usr/lib/x86_64-linux-gnu/libLLVM-4.0.so (0x00007f9a9ce38000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f9a9cab0000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f9a9c7a7000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f9a9c590000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9a9c1c9000)
libffi.so.6 => /usr/lib/x86_64-linux-gnu/libffi.so.6 (0x00007f9a9bfbf000)
libedit.so.2 => /usr/lib/x86_64-linux-gnu/libedit.so.2 (0x00007f9a9bd87000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f9a9bb83000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007f9a9b95a000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f9a9b73c000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f9a9b522000)
/lib64/ld-linux-x86-64.so.2 (0x00005607270ed000)
libbsd.so.0 => /lib/x86_64-linux-gnu/libbsd.so.0 (0x00007f9a9b30b000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f9a9b103000)

Thank you for making ante public for the public to experiment with, to me it looks like a really interesting combination of memory efficiency and clean and expressive syntax.

missing newline at the end -> crash

I have file:

print "Start\n"

print "End\n"

where the last line DOES NOT end with newline.

The result:

O:\ante\ante-master\bin>ante test2.an
←[;3mtest2.an←[;m: ←[;1m3,7-15←[;0m     ←[;31merror: ←[;mCalled function was given 2 arguments but was declared to take
1
print "End\n"
←[;31m      ^^^^^^^^^←[;m

Compilation aborted.

Unnecessary phi instructions with if constructs returning void expressions

example code:

if true then
    puts("branch 1")
else
    puts("branch 2")

compiled with --emit-llvm -O0 produces:

@0 = private unnamed_addr constant [9 x i8] c"branch 1\00"
@1 = private unnamed_addr constant [9 x i8] c"branch 2\00"

define i8 @main() {
entry:
  br i1 true, label %then, label %else

then:
  call void @puts(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @0, i32 0, i32 0))
  br label %endif

else
  call void @puts(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @1, i32 0, i32 0))
  br label %endif

endif:
  phi void [ <badref>, %then ], [ <badref>, %else ]   ;  <---- this line
  ret i8 0
}

[tiny feature] if++

Gcc and clang (and I guess LLVM bitcode too) support hint __builtin_expect to the compiler. The hint is usually wrapped within macros:

if (likely(..)) { ... }
if (unlikely(...)) { ... }

and it has some minor impact:
http://blog.man7.org/2012/10/how-much-do-builtinexpect-likely-and.html

Why not support such featurette directly in the language? E.g.

if+ x > y then ... // here we expect the condition to be true most of the time
if- x > y then ... // we expect almost never go this way
if x > y then ...  // no idea or random chance

The feature may also serve as very succint documentation, this could be arguably the most useful function.

If Ante will ever have profile guided instrumentation it may detect clearly mistaken hints and show warning to the user, that his expectations were wrong.

elif may use this trick too. if-x would be compiler error.

Few questions

I have few questions and don't know better place where to ask.

  1. type Char = c8|c32 c:

    Is this union like in C, without any hidden tag? How are ambiguities resolved? Say:

    type foo = i8 | i16
    var foo  bar = i8 10
    var i32 baz  = bar
    
  2. ranges:

    for u in 0 ..^ testArr.len() do
       print(testArr#u)
    

    Will the testArr.len() be called repeatedly or will the compiler inspect the body of for and move it out?

  3. Type condition errors:

    type Teen =
       u8 age  in 10 .. 19
       Str name  where name.length > 0
    //TypeConditionErr
    let sara = Teen(18, "")
    

    If the condition is not true during runtime what will happen? Is/will there be some way to disable the check either explicitly or because some checking actions made before?

    In language.am there's sentence "TypeConditionErr is thrown". I though exceptions are not in the language.

first attempt

I tried to compile the tiny test:

print "Start"  


let x1 = 250u8
print x1

print "End"  

Screenshot of the result:
http://i.imgur.com/p1svZPF.png

Got 2 small problems:

  1. Console switched to colors, OK, but i did not switch back. See screenshot.
  2. Error message I got is uncomprehensible.
O:\ante\ante-master\bin>ante test.an

test.an: 5,7-8  error: Argument 1 of function is a(n) u8 but was declared to be a(n) c8* and there is no known implicit
cast
print x1
      ^^

Compilation aborted.

Correct way to pattern-match two-variable union?

I'm testing out pattern matching on tags, and the following code gives me an error:

type MaybeIntStr =
    | Some u8, Str
    | None

fun printmis : MaybeIntStr m
    match m with
    | Some i string -> printf "%d and %s" i string
    | None -> print "None"

let s = Some(1u8, "test")

printmis(s)

I can't replace i string with i, string without syntax errors, but trying to compile this as is gives the error pattern typecast's rval is not a identifier. My own debugging seemed to suggest that the compiler was taking i string as a single variable name instead of splitting it up. What should I be doing?

Couple of questions

  1. Will Ante support namespaces? If you are interested I have idea how to make them better than e.g. in C++.

  2. String interpolation: will it be possible to "intercept" this mechanism for certain specific cases? What I have in mind is advanced assert:

  assert(x > 0, "x = ${x}, y = ${y}, z = ${z}")

If assert happens I would like to use my own memory handling management when showing all these details, w/o worrying about accidentally running out of memory.

string literals concatenation

In file strInterpolation.an I noticed line:

print( "Hello, " ++ getMyString() ++ "!")

Why is the ++ needed here? These string has to be concatenated, nothing else can be done here. Why not the ability to omit this operator when the context is clear (and it is also clear where expression ends)?

print( "Hello, " getMyString() "!")

This would help e.g with generating HTML fragments, making it easier to the eyes.

Support for union types by the language?

Say I have:

type Char =  c8|c32 c
let Char ch = ...

Does the language support "polymorphic use" through union parameters? Say I have functions:

fun foo: ch8 par = ...
fun foo: c32 par = ...

// Now the compiler may insert run-time decision 
// which function to call. 
// It could also do compile-time check that all possibilities are covered, 
// that there's a foo overload for every union member
//
foo(ch)  // will this work?

Error in type inferencing generic balanced tree type

type Bt 't = 
   | Branch 't,'t
   | Leaf 't

let l = Leaf 3
let b = Branch(l, l)  //good

let invalid = Branch(l, 3) //invalid but type checker allows it and inferences Bt (Bt i32)

The code above is accepted by the compiler, but should be rejected as Branch(l, 3) should not match the data definition of Branch 't, 't

obj/f16.ao bootstrap

Do you want a pull request for properly bootstrapping obj/f16.ao?
e.g. darwin has no ELF.

roughly like this (but see #31):

--- Makefile
+++ Makefile
@@ -35,8 +35,10 @@ DEPFILES := $(OBJFILES:.o=.d)
 .DEFAULT: ante

 ante: obj obj/parser.o $(OBJFILES) $(ANOBJFILES)
-       @echo Linking...
-       @$(CXX) obj/parser.o $(OBJFILES) $(ANOBJFILES) $(LLVMFLAGS) -o ante
+       @echo Linking...
+       @$(CXX) obj/parser.o $(OBJFILES) $(LLVMFLAGS) -o ante
+       @$(MAKE) obj/f16.ao
+       @$(CXX) obj/parser.o $(OBJFILES) $(ANOBJFILES) $(LLVMFLAGS) -o ante

But there's more missing. ante needs to be called as ./ante unless you already bootstrapped it into the PATH.
And darwin needs make YACC=/opt/local/bin/bison as /usr/bin/bison is too old.

Are recursive types possible?

I've been trying to write a basic linked-list, but the type system doesn't accept the recursion. Is a forward declaration required?

Compiler segfault dereferencing untyped pointer.

I don't know if this is an oversight of the type system, but trying to compile this on my machine makes a segfault.

Box<'t> = 't* contents

let b = Box 1u8

printf "Box contents: %d" (@b.contents)

Obviously the box instance isn't well-typed and the pointer type isn't determinable, which might be causing the issue. let b = Box (new 1u8) works as expected.

Also interesting: if you try to use string interpolation, print "Box contents: ${(@(b.contents)}" identifies that the type of b.contents is actually 't*, and it complains that this isn't a Str. Is the type somehow valid without all the parameters being set?

exception mentioned in language spec

The file language.an contains line:

arr -= 3 //Note: this will throw an exception if the array's size becomes < 0

What does it mean exception here? Application crash or something ala C++ with exception hierarchies and various levels of exception safety? This word is not mentioned anywhere else in the spec.

Segfault during compilation

The following program gives me a segfault.

type TestType = u8 contents

fun printcontents: TestType t
    printf "%d" t.contents

printcontents(TestType(1_u8))

gdb points to the culprit being line operator.cpp line 653, where extTy is null, for some reason.

format of numbers

Currently underscore is supported as visual separator of digits.

I remember that in some language (I forgot which one) they use ' (single quote) for this exact purpose.

Perhaps this could be per-project option. Default could be underscore, and in project configuration one could remove it or other separator(s).

If the model of "preprocessing" sources according to requested style is adopted then separators in stdlib could be "fixed" too.

In theory it would be also possible to fix number formatting according to culture, say from 1,2 to 1.2.

Can't create new single value union instance in let binding

type Basic = | First u8 | Second u8, u8

// Fails
let b = First 1u8
// Also fails
let b = First(1u8)

// Fine
let b = Second(1u8, 1u8)

Attempting to create a First in the let binding produces the error message Invalid type cast u8 -> First.

Use editline or readline for the repl

It would be nice if the repl used editline or readline or something like that so there could be history search and left/right arrows. I can make a pr if you're interested.

Usefulness of type condition errors

This example got me thinking:

type Teen =
  u8 age  in 10 .. 19
  Str name  where name.length > 0
//TypeConditionErr
let sara = Teen(18, "")

How much useful is this feature?

I'll ignore simpler things like pointer nulability checking and enforcing integer ranges and will write about string restrictions and more complicated compile time checks.

  1. Programs usually do not have that many literals in code. Complex data are read from some external source, not hardcoded. Even hardcoded strings may go first through internationalization layer.

  2. The checking won't be so simple.

Instead of where name.length > 0 one may want a function which decides that Jon Snow is a valid name and ougs872kjgs is not. One would not create such a complicated function only for rare compile time use.

Complicated checks also take time and one may not want compiler to insert them automatically, e.g every time a structure is copied. (This is IMHO the main problem with language level preconditions, postconditions and class invariants: they are nice and all but get invoked over and over, even when one knows this is unneccessary.)

  1. Useful checking may not be possible during compile time. The check could be whether the name is actually present in some database or whether the name is unique among all similar data loaded into memory.

expression quietly overflows

I am curious how numeric expression work in ante:

print "Start"  

let x1 = 250u8
let x2 = 250u8
let x3 = 250u8


var x4 = 999u8

x4 = (x1 * x2) / x3
printf "x4 = %u\n" x4


print "End"  

The result is 0, instead of the correct 1. Perhaps expressions should automatically (unless it can be proved overflow cannot happen) use the highest hardware supported numeral type to avoid quiet overflows and truncating. It is different from C rules but it should not be much slower.

Alternatively the C-like truncation may be default but with option to override it with something like:

no_overflow {
   .. calculations
} else {
  ... overflow/truncation happened
}

IIRC C# uses someting like this.

Type.init methods recompiled

Calling a Type's init method results in the method being recompiled each time it is called. The code:

type T = i32 i
fun T.init := T 0

let p = T()
let q = T()

Results in a binary containing the functions Pair_init and Pair_init.1, both copies of each other.

generated executable crash

print "Start"  


let x1 = 250u8
print x1

print "End"  

Compiles OK, generates the executable, this one prints the "Start" and then crashes (Windows shows dialog about problems, blah, blah).

LLVM DLL search not available on windows

Using ![macro] functions on windows that call non-ante functions (such as puts) often results in an error message:

LLVM ERROR: Tried to execute an unknown external function: puts

According to this stack overflow answer, the dlsym linking ante currently relies on is unavailable in windows:

LLVM will use dlsym() to find the symbols in the JIT program itself. Depending on your platform, [...] it might not be available at all (such as on Windows).

static & dynamic array unification

This is (only half baked) idea to unify static and dynamic arrays use. Static arrays and dynamic arrays (vectors) usually have different syntax leading to manual duplication of generics. Static ones are prone to degradation to pointers.

Reading language.am I think they are distinct now (because of the array -> pointer conversion).

Whether array is static or dynamic can be (I guess) deduced from its declaration. This information can be then used by the compiler.

If a function has static array as a parameter it would also secretly pass the known fixed size as parameter and current size as another one (I think this is needed to implement the ++= operator).

If a function has dynamic array as a parameter it would take pointer to its "vector" structure.

If a function is called with static array in one place and with dynamic array in another then the code (either source or AST) would be cloned and modified to handle both variants. Similarly for templates, they would be instantiated according to their use.

If a function has several array parameters then clones would be created for all combinations which were found.

Taking pointer to such functions would not be allowed by the compiler (because the clones cannot be distinguished by name).

Array as member of structure/tuple would not require any special handling.

If implemented then conversion of arrays to pointers could be perhaps dropped (except for FFI) and pointer arithmetic as well. I had never used pointer arithmetic anywhere but in degraded array context.

I do not have clear picture for multidimensional array. (I never used such a beast.)

enums

Few suggestions to improve enums.

  1. match on enums should require complete list of values, w/o the default (default would defeat the intention and may result in bug when another enum item is added later).

  2. Some enums may want to use global namespace (like in C):

    enum foo -> .Bar .Baz (accomplished by the leading dot)

    Both Bar and foo.Bar would be valid names. If the enum is very important for the application and used often short name is enough.

  3. Enum may be assigned string, to be directly usable in string context:

    enum Foo ->
      bar = "My Name 1"
      baz = "My Name 2"
    
    

    Default would be the stringified symbol. Empty string or nil may mean no automatic stringification.

  4. Aliases. This may be useful for SCADA applications where some cryptical names from the documentation have informal aliases.

    enum Foo ->
      NR_27_F7_3 = wheel 
      NR_00_H2_0
      NR_12_O3_1 = engine
    
    

    Formal name and alias could be used interchangeably.

  5. Enums may be defined "inline" together with related functions, to give a hint that these constructs belong together.

    // when return value is anonymous enum
    fun foo -> enum Bar Baz // namespace of Bar & Baz is foo
    
    var res = foo()
    
    match res with
      foo.Bar -> 
       foo.Baz ->
    

    and

    // when parameter is anonymous enum
    fun foo : (enum Bar Baz) param = 
    
    foo(Bar)
    

    and non-anonymous variants

    fun foo -> enum xyz -> Bar Baz 
    
    var foo.xyz res = foo()
    
    fun foo : (enum xyz -> Bar Baz) param 
    
    foo(xyz.Bar)
    

    Non-anonymous inlined enums would need to be used in "function context", meaning inside the block which calls the function, not separately or as a member of some structure. Restriction on use of the symbol should avoid misuse.

  6. Enum as valid integer range plus sideband value(s):

    enum FooResult ->
      NO_MEMORY // automatically assigned value outside valid result range, e.g. 101
      SOME_OTHER_ERROR
      1 .. 100 // valid results
    
    fun foo -> FooResult  = ...
    
    match foo() with -> // exhaustive match
      1 .. 50 -> 
      51 .. 100 ->
      NO_MEMORY ->
      SOME_OTHER_ERROR ->
    

    Here foo() may return valid result (the number) or error. No need to create complicated types which need more memory or to pretend that some magic number (-1) means error and hope programmer won't forget about it.


Complex example:

enum Foo ->
  Bar = 1 = something = "Bar"
  Baz  // = 2 = "Baz"
  Grr = "Hmm" // = 3
  Frr = .wheel // = 4 = "Frr",  'wheel' symbol is in global namespace

Possible new initialization syntax

Currently in Ante, the only way to initialize objects is with the typecast syntax Type val. Initializing larger objects with several fields is done by casting a tuple to the desired type: Type (val1, val2, ..., valN). This syntax is not ideal for larger types. In the Vec example below, it is difficult to tell if the len or cap field is being initialized to 0u32 without memorizing/referencing the Vec type. With the new syntax, the type is free to change the ordering of its fields.

The new syntax proposed here is in addition to the current syntax and does not introduce any new keywords. It is meant for the initalization of larger objects, and enforces named fields initialization rather than initialization by the order of the arguments.

Current syntax:

type Vec 't = ['t] data, u32 len cap

Vec([8 u32](), 0u32, 8u32)

Proposed syntax:

type Vec 't = ['t] data, u32 len cap

Vec with
    data = [8 u32]()
    len = 0u32
    cap = 8u32

[feature] metametaprogramming

This is feature suggestion based on the first (and shallow) reading of the spec.

Problems which it may solve:

  1. Libraries tend to grow in complexity and became unusable.
  2. Solving naming style (CamelCase, using_underscores, etc) conflicts.
  3. Solving "parenthesis versus significant whitespace" conflict.

Imagine a new project. Developer states (perhaps in a project specification file) that he wants to use parenthesis and underscored_names everywhere. The compiler looks up actually imported files from standard library (and 3rd party libraries), modifies them according to the wish and copies them somewhere into the project directory. Developer then sees only code formatted according to his wishes.

The libraries would need to be written in form that allows automatic conversion.


Possibilities for problem 3: Python style, C parenthesis with different styles where to place the brackets, perhaps even Ruby style.


Possibilities for problem 2: CamelCase, Ada_Style, underscores_everywhere, possibly also style-with-minuses-as-separators. Case may or may not be made significant. Language keywords may be converted into uppercase.

Syntax should be provided for names which cannot be written in different way for whatever reason, e.g. !! prior the name or at the top of library.

The compiler may even enforce use of given style (ala gofmt).


Problem 1 can be solved this way:

Library writer would announce features which can be selectively enabled, something as:

fetaures 
{
  MY_FEATURE1 "short description"
  MY_FEATURE2 "description"
  XYZ "..."
}

at the top of the library. Library code will be filled with something as C conditional compilation:

@if(MY_FEATURE2) 
fun xyz : ...
@fi

It would be ugly and complex but the end user won't see it (unlike in C/C++). All the hard work and complexity would be on library writer only.

Then the user would specify (perhaps in project configuration file):

library foo uses features MY_FEATURE1, XYZ, ABC

and the compiler would preprocess imported libraries and remove all parts that are not needed. Result files will be placed into project directory. Programmer would see only the code he requested, w/o parts he doesn't need and w/o the preprocessor directives.

The import directive would stay as it is now.

3rd party library may request certain feature to be present, e.g.

import "foo" needs XYZ

and if this library is used by the app then the feature must be also specified by the project.

Error when compiling tests/list.an

tests/list.an: 10,5     error: If condition's then expr's type List<'t> does not match the else expr's type List<i32>
    if l.next != void* 0 then
    ^

Type mismatch in the if expression that looks to be caused by failure to bind a generic return type in some contexts.

Windows port?

Do you have a plan to port Ante on Win32? Is there something where I could help? I would try myself, but I read such horror stories about LLVM ...

Building instructions for Windows

Could you please write down how do you build the Windows version? I may try to make it working under MSVC. Should this succeed it would allow me to use the debugger and, perhaps get some understanding of the code.

Generic function overload error

The following code snippet:

type Maybe<'t> =
   | Some 't
   | None

fun div: 't a b -> Maybe<'t>
    if b == 0 then None
    else Some(a/b)

div 2 4
div 5.0 0.0

(Incorrectly) issues the following error:

u.an: 10,1-3    error: No matching candidates for call to div with args (f64, f64)
...
u.an: 5,5-7     note: Candidate function with params (i32, i32)
...
u.an: 5,5-7     note: Candidate function with params (i32)

In which the second candidate should not exist

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.