Skip to content

Commit

Permalink
jule: add the export directive
Browse files Browse the repository at this point in the history
  • Loading branch information
mertcandav committed Sep 16, 2024
1 parent c076f4c commit 0808663
Show file tree
Hide file tree
Showing 10 changed files with 81 additions and 11 deletions.
4 changes: 3 additions & 1 deletion src/julec/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,6 @@ Actually, JuleC just generates C++ code for now.

- **(3)** Scope part of deadcoe elimination optimizations, should be executed after other optimizations. Because other optimzations may will change code structure, so some scope deadcode elimination cases may occur. This possible optimizations cannot catched by scope optimizer if scope deadcode elimination optimizations applied before other independent middle-end optimizations.

- **(4)** For C/C++ IRs, include linked headers before the API. Otherwise it may cause compilation errors. For example, on Windows, `winsock2.h` must be included before `windows.h`. In a case where the API includes `windows.h` it is against this to later include `winsock2.h`.
- **(4)** For C/C++ IRs, include linked standard headers before the API. Otherwise it may cause compilation errors. For example, on Windows, `winsock2.h` must be included before `windows.h`. In a case where the API includes `windows.h` it is against this to later include `winsock2.h`.

- **(5)** Since user defined headers may use exported definitions of Jule, they must be imported after Jule declarations. Otherwise, compilation errors may occur.
2 changes: 1 addition & 1 deletion src/julec/obj/cxx/expr.jule
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ impl exprCoder {

fn operatorOverloadingUnary(mut &self, mut &s: &StructIns, op: TokenId, mut e: compExprModel) {
const Unary = true
f := obj::FindOperator(s, op, Unary)
mut f := obj::FindOperator(s, op, Unary)
if f == nil {
panic("unary operator overloading is not exist, this is an implementation mistake")
}
Expand Down
14 changes: 12 additions & 2 deletions src/julec/obj/cxx/ident.jule
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ impl identCoder {
identCoder.writeIdentTo(buf, ident)
}

static fn func(mut &buf: StrBuilder, &f: &Fn) {
static fn func(mut &buf: StrBuilder, mut &f: &Fn) {
match {
| f.Binded:
buf.WriteStr(f.Ident)
Expand All @@ -96,10 +96,15 @@ impl identCoder {
buf.WriteStr("static_")
}
}
export := obj::FindDirective(f.Directives, Directive.Export)
if export != nil {
buf.WriteStr(export.Args[0].Kind)
ret
}
identCoder.toOut(buf, f.Ident, uintptr(f))
}

static fn funcIns(mut &buf: StrBuilder, &f: &FnIns) {
static fn funcIns(mut &buf: StrBuilder, mut &f: &FnIns) {
if f.IsBuiltin() {
// Do not use [identCoder.writeIdentTo] for this.
// Built-in functions are always ASCII.
Expand Down Expand Up @@ -180,6 +185,11 @@ impl identCoder {
| v.Scope != nil:
identCoder.toLocal(buf, v.Token.Row, v.Token.Column, v.Ident)
|:
export := obj::FindDirective(v.Directives, Directive.Export)
if export != nil {
buf.WriteStr(export.Args[0].Kind)
ret
}
identCoder.toOut(buf, v.Ident, uintptr(v))
}
}
Expand Down
22 changes: 17 additions & 5 deletions src/julec/obj/cxx/object.jule
Original file line number Diff line number Diff line change
Expand Up @@ -459,25 +459,31 @@ impl ObjectCoder {
self.write("#define __JULE_DISABLE__SAFETY\n")
}

// Include binded libraries here, before the API header.
// Include binded standard library headers here, before the API header.
// See developer reference (4).
self.links()
self.links(true)

self.write("\n\n#include \"")
self.write(build::PathApi)
self.write("\"\n\n")
}

fn links(mut &self) {
fn links(mut &self, std: bool) {
for _, used in self.ir.Used {
match {
| !used.Binded:
continue
| build::IsStdHeaderPath(used.Path):
if !std {
continue
}
self.write("#include ")
self.write(used.Path)
self.write("\n")
| build::IsValidHeaderExt(path::Ext(used.Path)):
if std {
continue
}
self.write("#include \"")
self.write(used.Path)
self.write("\"\n")
Expand Down Expand Up @@ -542,7 +548,7 @@ impl ObjectCoder {
fn structureDestructor(mut &self, mut &s: &StructIns) {
// Dispose method must be non-static
const Static = false
disposeMethod := s.FindMethod("Dispose", Static)
mut disposeMethod := s.FindMethod("Dispose", Static)
mut disposed := FuncPattern.Dispose(disposeMethod)
// Call destructor if implemented.
if !disposed {
Expand Down Expand Up @@ -1065,6 +1071,12 @@ impl ObjectCoder {
self.write("\n\n")
self.declPos = self.Buf.Len()
self.globalDecls()

// Include user-defined libraries here.
// See developer reference (5).
self.write("\n\n")
self.links(false)
self.write("\n\n")
}

fn structureMethods(mut &self, mut &s: &StructIns) {
Expand Down Expand Up @@ -1167,7 +1179,7 @@ impl ObjectCoder {

fn pushInit(mut &self, mut &pkg: &Package) {
obj::IterFiles(pkg, fn(mut &file: &SymbolTable) {
for _, f in file.Funcs {
for (_, mut f) in file.Funcs {
if f.Ident == build::InitFn {
self.indent()
identCoder.func(self.Buf, f)
Expand Down
2 changes: 1 addition & 1 deletion src/julec/obj/cxx/scope.jule
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ impl scopeCoder {
fn operatorOverloadingAssign(mut &self, mut &s: &sema::StructIns, mut &l: &sema::OperandExprModel,
mut &r: &sema::OperandExprModel, op: lex::TokenId) {
const Unary = false
f := obj::FindOperator(s, op, Unary)
mut f := obj::FindOperator(s, op, Unary)
if f == nil {
panic("binary operator overloading is not exist, this is an implementation mistake")
}
Expand Down
1 change: 1 addition & 0 deletions std/jule/build/directive.jule
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ enum Directive: str {
Namespace: "namespace",
Deprecated: "deprecated",
Test: "test",
Export: "export",
}

// Reports whether directive is top-directive.
Expand Down
1 change: 1 addition & 0 deletions std/jule/build/log.jule
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ enum LogMsg: str {
InvalidComptimeIter: `comptime iterations can only be range iteration`,
InvalidComptimeTypeMatchExpr: `comptime type-match expressions can take only type declarations`,
WrongRetForward: "function return forwaring is wrong\n want (@)\n have (@)",
ExportedUsedAsAnonymous: `define @ is exported for backend so you cannot use as anonymous function`,

// Suggestions.
ExpectedIdentifier: `write an identifier because identifier expected`,
Expand Down
42 changes: 42 additions & 0 deletions std/jule/sema/directive.jule
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ impl directiveChecker {
ret
}

// remove quotes
d.Args[0].Kind = arg.Kind[1:len(arg.Kind)-1]

// Push relevant directives.
Expand Down Expand Up @@ -133,6 +134,7 @@ impl directiveChecker {
ret
}

// remove quotes
d.Args[0].Kind = arg.Kind[1:len(arg.Kind)-1]
}

Expand All @@ -157,6 +159,44 @@ impl directiveChecker {
}
}

fn checkExport(mut self, mut &d: &ast::Directive) {
match type self.o {
| &Fn:
f := (&Fn)(self.o)
if f.Binded || f.IsInit() || f.IsEntryPoint() || f.IsMethod() || len(f.Generics) > 0 {
self.s.pushErr(d.Tag, LogMsg.UnsupportedDirective, d.Tag.Kind)
ret
}
| &Var:
v := (&Var)(self.o)
if v.Binded || v.Constant {
self.s.pushErr(d.Tag, LogMsg.UnsupportedDirective, d.Tag.Kind)
}
|:
self.s.pushErr(d.Tag, LogMsg.UnsupportedDirective, d.Tag.Kind)
ret
}
if len(d.Args) > 1 {
self.s.pushErr(d.Args[1], LogMsg.ArgumentOverflow, d.Tag.Kind)
ret
}
if len(d.Args) < 1 {
self.s.pushErr(d.Tag, LogMsg.MissingExpr)
ret
}
arg := d.Args[0]
if arg.Id != TokenId.Lit {
self.s.pushErr(arg, LogMsg.InvalidSyntax)
ret
}
if arg.Kind[0] != '"' {
self.s.pushErr(arg, LogMsg.InvalidSyntax)
ret
}
// remove quotes
d.Args[0].Kind = arg.Kind[1:len(arg.Kind)-1]
}

fn checkDirective(mut self, mut &d: &ast::Directive) {
match d.Tag.Kind {
| Directive.Cdef:
Expand All @@ -169,6 +209,8 @@ impl directiveChecker {
self.checkDeprecated(d)
| Directive.Test:
self.checkTest(d)
| Directive.Export:
self.checkExport(d)
| Directive.Build
| Directive.Pass:
self.s.pushErr(d.Tag, LogMsg.UnsupportedDirective, d.Tag.Kind)
Expand Down
2 changes: 2 additions & 0 deletions std/jule/sema/eval.jule
Original file line number Diff line number Diff line change
Expand Up @@ -3087,6 +3087,8 @@ impl eval {
}
if !f.Decl.Statically && f.Decl.IsMethod() {
self.s.pushErr(expr.Token, LogMsg.MethodNotInvoked)
} else if findDirective(f.Decl.Directives, Directive.Export) != nil {
self.s.pushErr(expr.Token, LogMsg.ExportedUsedAsAnonymous, f.Decl.Ident)
} else {
f.AsAnon = true
}
Expand Down
2 changes: 1 addition & 1 deletion std/jule/sema/type2.jule
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use ast for std::jule::ast::{
TupleExpr,
FnCallExpr,
}
use std::jule::build::{LogMsg, Logf}
use std::jule::build::{Directive, LogMsg, Logf}
use lit for std::jule::constant::lit
use std::jule::lex::{Token, Ident, IsIgnoreIdent, IsAnonIdent}
use std::internal::strings::{StrBuilder}
Expand Down

0 comments on commit 0808663

Please sign in to comment.