Coder Social home page Coder Social logo

elz's Introduction

elz

Rust Coverage Status

Installation

git clone https://github.com/elz-lang/elz.git
cd elz && cargo install

Features

Type

  • void
  • int
  • f64
  • bool
  • string
  • List[T] TODO: #200

Top level construction

  • Variable
  • Function
  • Class
  • Trait, TODO: #241, #225, #250

Changelog

Take a look at CHANGELOG

elz's People

Contributors

dannypsnl avatar yanherchen 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

Watchers

 avatar  avatar  avatar  avatar  avatar

elz's Issues

How to link std-c API

Make sure you have clang(the point is generated LLVM layout, so you, of course, can use other things)

Create a C file had use printf

// main.c
#include <stdio.h>
int main() {
  printf("Print something: %s", "Another string");
}

Then use clang -S -emit-llvm main.c compile it. You will get something like:

; ModuleID = 'main.c'
source_filename = "main.c"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.13.0"

@.str = private unnamed_addr constant [20 x i8] c"Print something: %s\00", align 1
@.str.1 = private unnamed_addr constant [15 x i8] c"Another string\00", align 1

; Function Attrs: noinline nounwind optnone ssp uwtable
define i32 @main() #0 {
  %1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.1, i32 0, i32 0))
  ret i32 0
}

declare i32 @printf(i8*, ...) #1

attributes #0 = { noinline nounwind optnone ssp uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.module.flags = !{!0, !1}
!llvm.ident = !{!2}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 7, !"PIC Level", i32 2}
!2 = !{!"clang version 6.0.0 (tags/RELEASE_600/final)"}

Copy printf declaration into your IR code. Then try it.

ps. It just a experimental way to detect how can it work, not good solution

[Bug]typename llvm::Value, llvm::Constant* argument of incompatible type!

Problem you meet

As title, incompatible type, need to read LLVM doc then rewrite that.

Error Log

elz: ../../../../../include/llvm/Support/Casting.h:255: typename llvm::cast_retty<X, Y*>::ret_type llvm::cast(Y*) [with X = llvm::Constant; Y = llvm::Value; typename llvm::cast_retty<X, Y*>::ret_type = llvm::Constant*]: Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
SIGABRT: abort
PC=0x7fc76fe19428 m=0 sigcode=18446744073709551610
signal arrived during cgo execution

goroutine 1 [syscall, locked to thread]:
runtime.cgocall(0x541db0, 0xc4200f1d80, 0x2865ce8)
	/usr/lib/go-1.9/src/runtime/cgocall.go:132 +0xe4 fp=0xc4200f1d50 sp=0xc4200f1d10 pc=0x419894
llvm.org/llvm/bindings/go/llvm._Cfunc_LLVMConstFMul(0x2865c10, 0x2867ee8, 0x0)
	llvm.org/llvm/bindings/go/llvm/_obj/_cgo_gotypes.go:2853 +0x4e fp=0xc4200f1d80 sp=0xc4200f1d50 pc=0x4f433e
llvm.org/llvm/bindings/go/llvm.ConstFMul.func1(0x2865c10, 0x2867ee8, 0x2865110)
	/home/routedan/workspace/go/src/llvm.org/llvm/bindings/go/llvm/ir.go:870 +0xa3 fp=0xc4200f1db8 sp=0xc4200f1d80 pc=0x4f6853
llvm.org/llvm/bindings/go/llvm.ConstFMul(0x2865c10, 0x2867ee8, 0x2867ee8)
	/home/routedan/workspace/go/src/llvm.org/llvm/bindings/go/llvm/ir.go:870 +0x35 fp=0xc4200f1de0 sp=0xc4200f1db8 pc=0x4f5a05
github.com/elz-lang/elz/ast.(*BinaryExpr).Codegen(0xc420133080, 0xc420132fc0, 0xc42011e3d4)
	/home/routedan/workspace/go/src/github.com/elz-lang/elz/ast/expr.go:41 +0x12c fp=0xc4200f1e30 sp=0xc4200f1de0 pc=0x4f758c
github.com/elz-lang/elz/ast.(*VarDefination).Codegen(0xc420126f80, 0xc420132fc0, 0x2867e28)
	/home/routedan/workspace/go/src/github.com/elz-lang/elz/ast/ast.go:34 +0xb5 fp=0xc4200f1e88 sp=0xc4200f1e30 pc=0x4f70e5
github.com/elz-lang/elz/listener.(*ElzListener).Module(0xc420126ec0, 0x90c0c0)
	/home/routedan/workspace/go/src/github.com/elz-lang/elz/listener/listener.go:27 +0x5b fp=0xc4200f1ef0 sp=0xc4200f1e88 pc=0x53c62b
main.main()
	/home/routedan/workspace/go/src/github.com/elz-lang/elz/main.go:23 +0x203 fp=0xc4200f1f80 sp=0xc4200f1ef0 pc=0x53f553
runtime.main()
	/usr/lib/go-1.9/src/runtime/proc.go:195 +0x226 fp=0xc4200f1fe0 sp=0xc4200f1f80 pc=0x441776
runtime.goexit()
	/usr/lib/go-1.9/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc4200f1fe8 sp=0xc4200f1fe0 pc=0x46a501

rax    0x0
rbx    0x7fc7748da000
rcx    0x7fc76fe19428
rdx    0x6
rdi    0x2b76
rsi    0x2b76
rbp    0x7fc770ebb0f8
rsp    0x7ffcd4dcc638
r8     0xfefefefefefefeff
r9     0x1
r10    0x8
r11    0x202
r12    0xff
r13    0x7fc770ee46e0
r14    0x13
r15    0xc
rip    0x7fc76fe19428
rflags 0x202
cs     0x33
fs     0x0
gs     0x0

Commit Rules

[add]: create a new file or add a new function.
[feat]: create a new feature. !!! A known feature, if not, create an issue then implement it
[fix]: Fixed known bug, !!! If this bug is an unknown bug, please create an issue then fixed it.
[clean]: comment, reformat(gofmt only), refactor. Include improving tests
[test]: new test

Support basic type for convenience

  • i8 *
  • i32 *
  • i64 *
  • u8
  • u16
  • u32
  • u64
  • f32 *
  • f64 *
  • [V; len] as arr<V, len>, machine type?
  • str *

* mean more important than remains

Can convert arr<V, len> to list<V> with length len

How cast working in LLVM

trunc

Syntax: <result> = trunc <ty> <value> to <ty2> ; yields ty2

The ‘trunc’ instruction takes a value to trunc, and a type to trunc it to. Both types must be of integer types or vectors of the same number of integers. The bit size of the value must be larger than the bit size of the destination type, ty2. Equal sized types are not allowed.

The ‘trunc’ instruction truncates the high order bits in value and converts the remaining bits to ty2. Since the source size must be larger than the destination size, trunc cannot be a no-op cast. It will always truncate bits.

%X = trunc i32 257 to i8                        ; yields i8:1
%Y = trunc i32 123 to i1                        ; yields i1:true
%Z = trunc i32 122 to i1                        ; yields i1:false
%W = trunc <2 x i16> <i16 8, i16 7> to <2 x i8> ; yields <i8 8, i8 7>

zext

Syntax: <result> = zext <ty> <value> to <ty2> ; yields ty2

The ‘zext’ instruction takes a value to cast, and a type to cast it to. Both types must be of integer types or vectors of the same number of integers. The bit size of the value must be smaller than the bit size of the destination type, ty2.

The zext fills the high order bits of the value with zero bits until it reaches the size of the destination type, ty2.

When zero extending from i1, the result will always be either 0 or 1.

%X = zext i32 257 to i64              ; yields i64:257
%Y = zext i1 true to i32              ; yields i32:1
%Z = zext <2 x i16> <i16 8, i16 7> to <2 x i32> ; yields <i32 8, i32 7>

CGO flags problem could happen at Go 1.9.4

If you see a compilation error while compiling your code with Go 1.9.4 or later as follows,

go build llvm.org/llvm/bindings/go/llvm: invalid flag in #cgo LDFLAGS: -Wl,-headerpad_max_install_names you need to set up $CGO_LDFLAGS_ALLOW to allow a compiler to specify some linker options:

$ export CGO_LDFLAGS_ALLOW='-Wl,(-search_paths_first|-headerpad_max_install_names)'

Memory Handle in Elz

We have three kinds of normal var form in Elz.

  1. Global Var
pi = 3.1415926
  1. Local immutable
fn foo() {
  let flag = 0
}
  1. Local mutable
fn foo() {
  let mut i = 0
}

Use C++ implement llvm compiler

Unfortunately, llir/llvm can not do something I want, and go-llvm binding has poor document.
I think should use C++ to write the translate part, but we can use Go write the remain part.

[impl]Function Context

Because we can have a lot of block in the function, even function in the function. And the variable accessible only in function, we need to impl function context for the project.

Example:

fn main() {
  let a = 1
  let b = a
}

Write more contributing

Like how to use antlr
How LLVM IR mapping to Elz
How ast::Codegen work with type system
ps. ast: Abstract Syntax Tree

[Bug]ast.Id should load variable

Problem you meet

compile Test file meet error message(go runtime)

Error Log

var panic: runtime error: invalid memory address or nil pointer dereference

What happened?

As title, use a llvm.Value of variable as value is invalid

[Bug]Can not compile if access value from other variable

The problem is because the implementation just now will try to get the Type info we will have after codegen.
But those Type info is needed at parse time.
So we will get invalid address(the data structure we put vars even don't have Initialize)

Utils

A util module, put something like Stack data structure.

How to handle parameters

I see a lot of practices use p.addr, allocate a stack for a parameter, then store the data into an address, final load data from these addresses.

Example of C:

define i32 @add(i32, i32) #0 {
  %3 = alloca i32, align 4
  %4 = alloca i32, align 4
  store i32 %0, i32* %3, align 4
  store i32 %1, i32* %4, align 4
  %5 = load i32, i32* %3, align 4
  %6 = load i32, i32* %4, align 4
  %7 = add nsw i32 %5, %6
  ret i32 %7
}

Original Code:

int add(int l, int r) {
  return l + r;
}

[Bug]LLVM can't compile now

If you think you meet a bug, here.

Problem you meet

Can't compile elz because the problem from dependency

Error Log

go build llvm.org/llvm/bindings/go/llvm: invalid flag in #cgo LDFLAGS: -Wl,-search_paths_first

[Next Release] v0.0.1

I think v0.0.1 should contain:

  • primitive types: str, num, and it's basic operation
  • the basic function can only work with str, num
  • the error message can help to find out bugs in the program
  • testing of the parser about num, str expression

Edit after 2018-1-30 12:24

  • update antlr dependency 4.7.0 -> 4.7.1
  • have fn main to have a workable executable

Edit after 2018-1-30 14:44

  • Support more Unicode to be Ident's char
  • Support #23 grammar

[TODO]Generate function correctly

As title, and this feature should be released at v0.0.1.
For example:

fn add(lv: num, rv: num) -> num {
  return lv + rv
}

Should be compile to

define float @add(float, float) {
  ret %0 + %1 // not totally correct syntax, focus on concept
}

We need an Error Reporter

Because the solution: just panic will let us can only find one problem at once.
And we hope compiler can list all error(at least not just one) for the user.

It will become the critical issue when we implemented all expression

Feature: report error logs

[impl] `as` expression

as expression for i64, f64

fn main() {
  let a = 1.2 + 3 // it will cause error
  let b = 1.2 + 3 as f32 // this can pass
}

The example shows the result of this issue's want, as expression can convert the expression to the convertible certain type.

TODO:

  • as expression AST ~> ast/as_expr.go & following test

Create test for parser

I think create test flow from now on is important.
Else the code base will only become more and more complex.

[Feat]compile to C++

The reason is that seems LLVM is not pretty stable(go-llvm only), I will add another choice that compiles to C++. So that we can have an alternative to use when go-llvm can't work.

The reason not Nim but C++ is because already found some features of Nim is not suit for elz. For example, in Nim, slice_a equals to sliceA, that is auto conversion. And method also is a problem, proc a(self: t) let t can't have a property call a, but it should in elz.

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.