Skip to content

Commit

Permalink
Support Nim + C (#66)
Browse files Browse the repository at this point in the history
  • Loading branch information
srz-zumix authored Sep 1, 2021
1 parent e98b435 commit 3cfb797
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 12 deletions.
2 changes: 2 additions & 0 deletions samples/command/src/nim/c/test.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
void c_test1();
void c_test2();
11 changes: 11 additions & 0 deletions samples/command/src/nim/c/testA.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "test.h"
#include <stdio.h>

void c_test1()
{
printf("c_test1\n");
}
void c_test2()
{
printf("c_test2\n");
}
7 changes: 7 additions & 0 deletions samples/command/src/nim/c/testB.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "test.h"
#include <stdio.h>

void c_test3()
{
printf("c_test3\n");
}
14 changes: 14 additions & 0 deletions samples/command/src/nim/sample.nim
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ import test6 except Hoge6, Fuga6
from test7 import Test7, Fuga7
import "subdir/test8"


{.push header:"c/testA.c".} # push test

proc c_test1*()
proc c_test2*()

{.pop.}

proc c_test3*(){.header:"c/testB.c"}

echo "Hello, Wandbox!"
Test1()
Test2()
Expand All @@ -20,6 +30,10 @@ Test7()
Fuga7()
Test8()

c_test1()
c_test2()
c_test3()

# Nim language references:
# https://nim-lang.org/
# https://nim-lang.org/docs/manual.html
63 changes: 51 additions & 12 deletions wandbox/__nim__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,79 @@

from .cli import CLI
from .runner import Runner
from .__cxx__ import CxxRunner


class NimRunner(Runner):

IMPORT_REGEX = re.compile(r'^\s*import\s*(.*?)(\s*except\s*.*|)$')
FROM_IMPORT_REGEX = re.compile(r'^\s*from\s*(\S*?)\s*import\s*(.*?)$')
C_PROC_REGEX = re.compile(r'^\s*proc.*{.*\.header\s*:\s*([\'"].*[\'"]).*}\s*$')
PUSH_HEADER_REGEX = re.compile(r'^\s*{\.push\s*.*header\s*:\s*([\'"].*[\'"]).*}$')

def __init__(self, lang, compiler, save, encoding, retry, retry_wait, prefix_chars='-'):
super(NimRunner, self).__init__(lang, compiler, save, encoding, retry, retry_wait, prefix_chars)
self.cxx = CxxRunner(lang, compiler, save, encoding, retry, retry_wait, prefix_chars)

def reset(self):
self.imports = []
self.cxx.reset()

def make_code(self, file, filepath, filename):
files = dict()
code = ''
for line in file:
m = self.IMPORT_REGEX.match(line)
codeline = re.sub(r'\s*#.*$', '', line)
m = self.IMPORT_REGEX.match(codeline)
if m:
modules = m.group(1).strip('\'"')
for module_name in modules.split(','):
files.update(self.get_imports(os.path.dirname(filepath), module_name.strip()))
files.update(self.get_imports(m, filepath))
else:
m = self.FROM_IMPORT_REGEX.match(line)
m = self.FROM_IMPORT_REGEX.match(codeline)
if m:
module = m.group(1).strip('\'"')
module_names = module.split('.')
if len(module_names) == 0:
files.update(self.get_imports(os.path.dirname(filepath), os.path.dirname(filepath)))
files.update(self.get_from_imports(m, filepath))
else:
m = self.C_PROC_REGEX.match(codeline)
if m:
files.update(self.get_c_header(m, filepath))
else:
module_name = os.path.join(*module_names)
files.update(self.get_imports(os.path.dirname(filepath), module_name))
m = self.PUSH_HEADER_REGEX.match(codeline)
if m:
files.update(self.get_c_header(m, filepath))
code += line
files[filename] = code
return files

def get_imports(self, path, module_name):
def get_c_header(self, m, filepath):
header = m.group(1).strip('\'"')
return self.get_c(os.path.dirname(filepath), header)

def get_c(self, path, filename):
module_path = os.path.normpath(os.path.join(path, filename))
if os.path.exists(module_path):
module_abspath = os.path.abspath(module_path)
if module_abspath not in self.imports:
return self.cxx.open_code(module_path, filename)
return dict()

def get_from_imports(self, m, filepath):
files = dict()
module = m.group(1).strip('\'"')
module_names = module.split('.')
if len(module_names) == 0:
files.update(self.get_import(os.path.dirname(filepath), os.path.dirname(filepath)))
else:
module_name = os.path.join(*module_names)
files.update(self.get_import(os.path.dirname(filepath), module_name))
return files

def get_imports(self, m, filepath):
files = dict()
modules = m.group(1).strip('\'"')
for module_name in modules.split(','):
files.update(self.get_import(os.path.dirname(filepath), module_name.strip()))
return files

def get_import(self, path, module_name):
module_file = module_name + '.nim'
module_path = os.path.normpath(os.path.join(path, module_file))
if os.path.exists(module_path):
Expand Down

0 comments on commit 3cfb797

Please sign in to comment.